close_btn
조회 수 134679 추천 수 0 댓글 2
?

단축키

Prev이전 문서

Next다음 문서

+ - Up Down Comment Print
?

단축키

Prev이전 문서

Next다음 문서

+ - Up Down Comment Print
rm(list=ls())
library(car)
setwd("C:\\Users\\JJS810\\Desktop")
student <-read.csv(list.files()[6],header=T)
View(student) 
str(student)
#Factor -> dummy variable
#plot & basic summary
summary(student) #missing value : 2
par(mfrow=c(2,2))
for (i in 6:9){
  plot(student[,i],student$target,main=colnames(student)[i])
}
#target과 독립변수간의 상관관계가 정확히 보이지 않는다. 
#numeric한 변수와 target간의 산점도
캡처1.PNG
#correlation
colnames(student)
cov.wt(student[,c(6:9,11)],cor=T)$cor
#target과 numeric한 변수들간에 약한 상관관계가 보인다.
#0.275~0.502 정도의 양의 상관관계가 보인다.

#how to find missing value
sum(is.na(student)) #missing value : 2
colSums(is.na(student)) #Topic : 1, ParentschoolSatisfaction : 1
#remove the missing value
which(is.na(student$Topic)) #78
which(is.na(student$ParentschoolSatisfaction)) #87
student$Topic[78];student$ParentschoolSatisfaction[87]
#missing value -> omit
student <- na.omit(student) #389obs -> 387obs

#dummy -> factor
#model.matrix()
#dummy variable about 2 levels
student$gender <- ifelse(student$gender=="F",1,0) #F=1, M=0
student$semester <- ifelse(student$semester=="F",1,0) #F=1, S=0
student$responsible <- ifelse(student$responsible=="Father",1,0) #Father=1, Mum=0
student$ParentAnsweringSurvey <-ifelse(student$ParentAnsweringSurvey=="Yes",1,0) #Yes=1 ,No=0
student$StudentAbsenceDays <- ifelse(student$StudentAbsenceDays=="Above-7",1,0) #Above-7=1, Under-7=0
student$ParentschoolSatisfaction <-ifelse(student$ParentschoolSatisfaction=="Good",1,0) #Good=1, bad=0
#duumy variable about 3, 8 levels
colnames(student)
section <- matrix(0,nrow=387,ncol=2)
colnames(section) <- paste0("dumsec",letters[1:2])
for (i in 1:387 ) {
  if(student[i,2]=="A"){section[i,1]<-1}
  else if(student[i,2]=="B"){section[i,2]<-1}
  else{}
}

levels(student$Topic) #8 levels
#"Arabic"  "Biology" "English" "French"  "History" "IT"     
#"Science" "Spanish"
topic <- matrix(0,nrow=387,ncol=7)
colnames(topic)<-paste0("dum",c("arab","bio","eng","fre","his","it","Sci"))
for (j in 1:387){
  if(student[j,3]=="Arabic"){topic[j,1]<-1}
  else if(student[j,3]=="Biology"){topic[j,2]<-1}
  else if(student[j,3]=="English"){topic[j,3]<-1}
  else if(student[j,3]=="French"){topic[j,4]<-1}
  else if(student[j,3]=="History"){topic[j,5]<-1}
  else if(student[j,3]=="IT"){topic[j,6]<-1}
  else if(student[j,3]=="Science"){topic[j,7]<-1}
  else{}
}

#merge data
student <- student[,-c(2,3)]
student <- cbind(student,section, topic)
str(student)

#regression
fit <-lm(target~.,data=student) #full model
summary(fit) #0.6097
vif(fit) #sqrt(vif)>2 : multicolinearity
vif(fit)[sqrt(vif(fit))>2] #dummy라 제거하기 애매하고 4~5사이이므로 그냥 놔두자.
#일반적으로 다중공선성의 경우 VIF가 10이하이면 없다고 판단할 수 있으므로, 공선성 문제는 없다고 생각하자.

#stepwise by AIC
library(MASS)
fit.aic<-stepAIC(fit,direction='both')
fit.aic$anova
fit1 <- lm(target ~ semester + responsible + raisehand + VisITedResources + 
             AnnouncementsView + ParentAnsweringSurvey + StudentAbsenceDays + 
             dumSci, data=student)
summary(fit1) #0.6151
plot(fit1) #42,46,329 이상치이고 200후반대부터 살짝 qqline을 벗어나는 영향을 보인다.
#정규성 여부 검정 - 단일 모집단 분포의 정규성 검정
par(mfrow=c(1,1))
qqnorm(fit1$residuals) #잔차를 확인해야 한다.
hist(fit1$residuals)
#살짝 qqline이 정규성을 약간 만족하지 않는 것으로 보인다.
#정확한 회귀진단은 뒤에서 자세히 다루겠다.

#forward
fit.con <-lm(target~1,data=student)
fit.full <- lm(target~.,data=student)

fit.forward <- step(fit.con, scope=list(lower=fit.con, upper=fit.full),direction="forward")
summary(fit.forward) #0.6151

#backward
fit.backward <- step(fit.full, scope=list(lower=fit.con, upper=fit.full),direction="backward")
summary(fit.backward) #0.6151

#회귀진단
diag.student <-ls.diag(fit1)
diag.student

#정규성검정
qqPlot(fit1,labels=row.names(student),id.metho="identify",simulate=TRUE,main="Q-Q PLOT")

#leverage = 이상치 , dffits,cooks = 영향치 
myregression<-function(x){
  h=hat(model.matrix(x))  
  d=dffits(x) 
  cutoff=4/((nrow(student)-length(x$coefficients)-2))
  par(mfrow=c(1,3))
  plot(h,type="h",main="leverage plot",ylab="leverage")
  plot(d,type="h",main = "dffits",ylab="dffits")
  plot(x,which=4,cook.levels = cutoff)
  par(mfrow=c(1,1))
}
myregression(fit1) #Cook's distance에서 13,42,46 번째가 이상치로 보인다. 
캡처2.PNG
outlierTest(fit1, cutoff=0.5) #42, 46 이상치 

#샤피로테스트,더빈왓슨테스트, 등분산성 테스트 
shapiro.test(residuals(fit1)) #통계량에 의한 정규성 검정, p-value :0.04698 -> reject H0 
#H0 : 모집단은 정규분포를 따른다...샤피로 테스트에서 귀무가설을 기각하므로 모집단이 정규성을 만족하지 않는다.
#즉 정규성 부분에서 문제가 발생한다....이 문제를 어떻게 해결할까?
durbinWatsonTest(fit1) #종속변수의 독립성 p값이 의미가 없어야지 자기상관이 없는것 
crPlots(fit1) #변수들의 선형성을 확인하였고, fitting 된 모델이 어느정도 잘 맞는다.
캡처3.PNG
ncvTest(fit1) #등분산성을 확인하는 테스트이고, p=0.2245947로 유의하지 않으므로 오차의 등분산성 만족 
spreadLevelPlot(fit1) #fitted vakye에 대한 스튜던트화 잔차를 시각화 
#아래의 그림에서 기존의 빨간선보다 잘 맞지 않는 것을 알 수 있다.
캡처4.PNG

#잔차 plot
residplot <- function(fit, nbreaks=10) {
  z <- rstudent(fit)
  hist(z, breaks=nbreaks, freq=FALSE,xlab="Studentized Residual",
       main="Distribution of Errors")
  rug(jitter(z), col="pink")
  curve(dnorm(x, mean=mean(z), sd=sd(z)),add=TRUE, col="blue", lwd=2)
  lines(density(z)$x, density(z)$y,col="red", lwd=2, lty=2)
  legend("topright",legend = c( "Normal Curve", "Kernel Density Curve"),
         lty=1:2, col=c("blue","red"), cex=.7)
}
residplot(fit1) #정규분포 어느정도 차이가 보인다. 
#qqnorm으로 확인 했을때, 정규성이 잘 안 맞는 것을 밑의 그림으로 한번 더 확인 할 수 있다.
캡처.PNG6.PNG
#선형모형 가정에 대한 전반적 검증
install.packages("gvlma")
library(gvlma)
gvmodel <- gvlma(fit1)
summary(gvmodel) #OLS 가정 만족한다.!!
#그런데 왜 정규성을 만족안할까? -> 혹시 이상치가 문제가 있는지 한번 더 확인해보자 
캡처5.PNG
#high leverage points
#위에서 정규성이 안 맞는 이유에서
library(ggplot2)
library(ggiraph)
library(moonBook)
par(mfrow=c(1,1))
hat.plot <- function(fit) {
  p <- length(coefficients(fit))
  n <- length(fitted(fit))
  y=hatvalues(fit)
  name=attr(hatvalues(fit),"names")
  df=data.frame(x=1:length(y),y=as.numeric(y),name=name)
  p1<-ggplot(df,aes(x=x,y=y,tooltip=name,data_id=x))+geom_point_interactive()
  yintercept2=2*p/n
  p1<-p1+geom_hline(aes(yintercept=yintercept2),col="orange",lty="dashed")
  yintercept3=3*p/n
  p1<-p1+geom_hline(aes(yintercept=yintercept3),col="red",lty="dashed")
  ggiraph(code=print(p1))
  
}                 
hat.plot(fit1) #red line : average hat보다 2배, 3배 높은 것을 의미
캡처.PNG7.PNG
#13,169,218,222,226,342 가 평균 hat보다 높게 있다.
#42,46,329 이상치
#위의 회귀진단을 바탕으로 관측치를 제거해보자.
#주의해야할 사항은 이상관측치가 흥미로운 데이터일수도 있다는 점
#따라서 원래는 이상치를 일일히 확인을 해봐야 한다.
#이상관측치 인덱스

student[c(13,42,46,169,218,222,226,329,342,354),]
plot(student$raisehand,student$target)
lines(smooth.spline(x=student$raisehand, y=student$target))

#여기서 이상치를 일일히 확인해서, 그 이유를 찾기에는 이 데이터에 대한 정보가 부족하다고 생각
#따라서 그냥 이상치를 제거하고 회귀분석을 진행하겠다.

#이상치를 제거한 모형 
student.rm <-student[-c(13,42,46,169,218,222,226,329,342,354),]
str(student.rm)
fit2 <-lm(target~.,data=student.rm)
fit.step2<- stepAIC(fit2,direction="both")
fit3 <- lm(target ~ responsible + raisehand + VisITedResources + ParentAnsweringSurvey + 
             StudentAbsenceDays + dumeng + dumit + dumSci,data=student.rm)
summary(fit3) #0.6369로 증가하고 모든 독립변수가 유의하다. 

#종속변수를 한번 표준화해보고 같은 독립변수에 회귀분석을 해보았다( 정규성문제때문에 한번해보았다.)
fit4 <- lm(scale(target) ~ responsible + raisehand + VisITedResources + ParentAnsweringSurvey + 
             StudentAbsenceDays + dumeng + dumit + dumSci,data=student.rm)
summary(fit4) #0.6369 : 위의 fit3와 같은 결과가 나온다.

par(mfrow=c(2,2))
plot(fit3)
vif(fit3) #다중공선성은 없다.
#위의 회귀진단을 다시 해보았다.
myregression(fit3) #20, 73, 329가 다시 이상치로 나온다. 
qqPlot(fit3,labels=row.names(student),id.method="identify",simulate=TRUE,main="Q-Q PLOT")
8.PNG
#여전히 Q-Q plot에서 약간씩 데이터가 정규성을 만족하지 않는다.
shapiro.test(residuals(fit3)) #통계량에 의한 정규성 검정, p-value :0.04334 -> reject H0 
durbinWatsonTest(fit3) #종속변수의 독립성 p값이 의미가 없어야지 자기상관이 없는것 
crPlots(fit3) #선형성 시각화
ncvTest(fit3) #등분산성 : 유의하지 않으므로 오차의 등분산성 만족 
spreadLevelPlot(fit3) #fitted vakye에 대한 스튜던트화 잔차를 시각화 
residplot(fit3)
#정규성 문제가 계속 생기기 때문에, 그 이유를 확인해보기 위해서 target 변수에 대해서 산점도를 그려보았다.
plot(student.rm$target) ; hist(student.rm$target) #완전히 정규분포를 따르지 않는다.
캡처9.PNG 

#여기서 아까 fit3 회귀진단했을 때, 이상치로 판단된 데이터에 대해서 다시 회귀분석을 한번 더 해보았다.
student.rm1 <- student.rm[-c(20,73,329),]
fit5 <- lm(as.formula(fit3),data=student.rm1)
summary(fit5)
shapiro.test(residuals(fit5)) #0.04963으로 p-value가 증가하였다.
#이런 방식으로 계속 회귀진단을 하고 이상치를 제거하다보면, 정규성만족을 시킬 수 있을 것 같다.
#이처럼 회귀분석에서 모집단의 정규성을 만족하지 않을 경우에는 그 이유로 정규분포가 아니거나, 이상치가 있거나
#왜도가 심할 경우이며, 이 경우에는 종속변수를 변환시키거나, 비모수방법인 Kruskal-Wallis test가 있다고 한다.
#하지만 비모수방법은 잘 모르기 때문에 고려하지 않고, 해석을 위해서 종속변수에 다른 변환은 하지 않겠다.
#또한 샤피로 테스트에서 p=0.046정도면 유의수준인 0.05보다 약간 낮기 때문에 조금 애매하다고 할 수 있다.
#아마도 이건 회귀분석을 진행하면서, 그 집단에 문제가 있을 수도 있고, 소표본이기 때문에 엄격한 정규성을 만족 못할 경우도 있다.


#interaction 교호작용까지 고려해보기 
colnames(student)
dum<-student[12:20]
#install.packages("multcomp")
#library(multcomp) #다중비교하는 패키지 
betahat <-coef(fit3)
vbetahat <-vcov(fit3)
#다중비교를 위해서 전처리전의 데이터를 불러온다.
setwd("C:\\Users\\JJS810\\Desktop")
student.factor <-read.csv(list.files()[7],header=T)
str(student.factor)
student.factor<-na.omit(student.factor)
mod <-lm(target~.,data=student.factor)
mod.topic <-glht(mod,linfct=mcp(Topic="Tukey"))
summary(mod.topic) #유의한게 없다.
mod.section <- glht(mod,linfct=mcp(section="Tukey"))
summary(mod.section)
mod.gender  <- glht(mod,linfct=mcp(gender="Tukey"))
summary(mod.gender)
mod.semester <- glht(mod, linfct=mcp(semester="Tukey"))
summary(mod.semester)
mod.answer <-glht(mod, linfct=mcp(ParentAnsweringSurvey="Tukey"))
summary(mod.answer) #유의!!!!
mod.school <-glht(mod, linfct=mcp(ParentschoolSatisfaction="Tukey"))
summary(mod.school)
mod.absence <-glht(mod, linfct=mcp(StudentAbsenceDays="Tukey"))
summary(mod.absence) #유의!!!
#parentsanswer 와 studentabsence 유의 

#처음에 student에서 stepAIC로 돌린 모형으로 테스트 
summary(aov(target~.,data=student)) #교호작용은 분산분석을 통해서 알아본다. 
fit.cor <-lm(target ~ responsible + raisehand + VisITedResources + ParentAnsweringSurvey + 
               StudentAbsenceDays + dumeng + dumit + dumSci+dumeng*dumit*dumSci, data=student.rm)
summary(fit.cor) #4 not defined because of singularities. 당연히 더미변수끼리는 singularity 때문에 NA로 나온다.
#probably getting that error because two or more of independent variables are perfectly collinear
colnames(student.rm)
fit.final <- lm(target ~ responsible + raisehand + VisITedResources+
                  dumeng + dumit + dumSci+ParentAnsweringSurvey*ParentAnsweringSurvey+StudentAbsenceDays*StudentAbsenceDays,data=student.rm)
summary(fit.final) #0.6356.... 결국 fit3와 같은 결과가 나온다.

#아예 처음부터 AIC로 교호작용을 고려해서 해보자.
colnames(student)
str(student)
fit.inter <- lm(target~gender+semester+responsible+raisehand*VisITedResources*AnnouncementsView*Discussion+ParentAnsweringSurvey+ParentschoolSatisfaction+StudentAbsenceDays
                +dumsecb+dumseca+dumarab+dumbio+dumeng+dumfre+dumhis+dumit+dumSci,data=student)
fit.aic.inter<-stepAIC(fit.inter,direction='both') #가변수를 제외한 numeric했던 변수끼리만 진행하였다.
#dumsecb~dumSci를 제외한 모든 변수들을 고려해보고 싶었지만, 너무 많은 경우를 고려해야되서 분석이 돌아가지 않는다.
fit.aic.inter$anova
fit.aic.step <- lm(target ~ semester + responsible + raisehand + VisITedResources + 
             AnnouncementsView + Discussion + ParentAnsweringSurvey + 
             StudentAbsenceDays + dumSci + raisehand:VisITedResources + 
             raisehand:Discussion + AnnouncementsView:Discussion, data=student) 
summary(fit.aic.step) #0.6242
Anova(fit.aic.step)
plot(fit.aic.step) #이상치 몇개를 제외하고 괜찮아 보인다. 42,46,329번
캡처.PNG9.PNG
shapiro.test(residuals(fit.aic.step)) #만족한다
vif(fit.aic.step) #공선성 발생하기 때문에 공선성을 제거하자.

#vif문제를 해결해보자. vif가 가장 큰 변수를 순차적으로 제거한다.
fit.aic1 <-lm(target ~ semester + responsible + raisehand + VisITedResources + 
                AnnouncementsView + Discussion + ParentAnsweringSurvey + 
                StudentAbsenceDays + dumSci + raisehand:VisITedResources + 
                raisehand:Discussion ,data=student)
vif(fit.aic1)

fit.aic2 <-lm(target ~ semester + responsible + raisehand + VisITedResources + 
                AnnouncementsView + Discussion + ParentAnsweringSurvey + 
                StudentAbsenceDays + dumSci + raisehand:Discussion ,data=student)
vif(fit.aic2)
summary(fit.aic2) #0.6133으로 낮아지고, 독립변수가 유의하지 않은 것이 생겼다.
Anova(fit.aic2)
shapiro.test(residuals(fit.aic2)) #0.04715로 다시 정규성을 만족하지 않는다.
qqPlot(fit.aic2,labels=row.names(student),id.method="identify",simulate=TRUE,main="Q-Q PLOT") 

#그럼 위에서 유의하지 않은 독립변수들을 제외하고 다시 한번해보자.
fit.aic3 <-lm(target ~ semester + responsible + raisehand + VisITedResources + 
                ParentAnsweringSurvey + StudentAbsenceDays ,data=student.rm)
summary(fit.aic3) #0.631
Anova(fit.aic3)
shapiro.test(residuals(fit.aic3))
qqPlot(fit.aic3,labels=row.names(student.rm),id.method="identify",simulate=TRUE,main="Q-Q PLOT")
#이렇게 하니까 정규성도 만족하고, R스퀘어도 괜찮고, 적당해보인다. 

####최종모형에 대한 F-test
fit.full <- lm(target~.,data=student.rm)
anova(fit.final, fit.full)
AIC(fit.final, lm(target~.,data=student.rm))
#두 모델의 F-test에서 p값이 0.9028로 유의하지 않으므로,
#fit.full에서 변수를 제거한 모형은 올바르다. 

####결론
#결국 fit.final에 대한 해석을 해보자면, 아래와 같은 식이 나옵니다.

결론.PNG
#즉, target에 대해서, responsible이 적고, studentAbsencedays가 적을 수록 target이 올라가며,
영어, IT, 과학 부분을 학생이 배울 수록 target이 올라감을 알 수 있습니다. (크 역시 영어와 과학, IT계열이 중요하네요!!)
나머지 변수는 coefficient가 적어서, 굳히 target과 연관지어 해석하기 애매한 변수로 취급해도 될 것 같습니다.

#번외 : 아예 가능한 모든 회귀를 진행해보자. 
#all possible regression
library(leaps) #all possible regression
fit.all <-regsubsets(target~.,data=student)
summary(fit.all)
plot(fit.all,scale="adjr2") #adjusted R^2
subsets(fit.all, statistic="cp", main="Cp plot for all possible regression")
abline(1,1, lty=3,col="blue")
colnames(student)
fit.leaps <-lm(target~responsible+raisehand+VisITedResources+ParentAnsweringSurvey+StudentAbsenceDays+dumSci,data=student)
summary(fit.leaps)
plot(fit.leaps) #qqline에서 126,42,46,13번째 이상치

#bic를 기준으로 모델 생성
rs <-summary(regsubsets(target~.,data=student,nbest=ncol(student))) #nbest : number of subsets
bic.best <- which(rs$bic==min(rs$bic))
bic.vars <- names(rs$which[bic.best,])[rs$which[bic.best,]][-1] #intercept를 제외
bic.model <- paste(bic.vars, collapse="+")
bic.model <- as.formula(paste("target~",bic.model)) #식을 도출

fit.bic <- lm(bic.model, data=student.rm)
summary(fit.bic) #0.6284

#aic를 기준으로 모델 생성
n <- nrow(student)
p <- apply(rs$which,1,sum)
aic <- rs$bic-log(n)*p+2*p
aic.best <- which(aic==min(aic))
aic.vars <- names(rs$which[aic.best,])[rs$which[aic.best,]][-1]
aic.model <-paste(aic.vars,collapse = "+")
aic.model <- as.formula(paste("target~",aic.model))

fit.aic <-lm(aic.model, data=student.rm)
summary(fit.aic) #0.6345

#adjusted R^2
rs1 <- regsubsets(target~.,data=student, nbest=1, nvmax=NULL, force.in = NULL, force.out = NULL)
summary.out <- summary(rs1)
as.data.frame(summary.out$outmat)
plot(rs1, scale="adjr2", main="adjusted R^2")
which.max(summary.out$adjr2) #10
adjr.best<-names(summary.out$which[10,])[summary.out$which[10,]][-1]
adjr.model <-paste(adjr.best,collapse="+")
adjr.model <-as.formula(paste("target~",adjr.model))

fit.adjr <-lm(adjr.model, data=student.rm)
summary(fit.adjr) #0.6364
vif(fit.adjr)
shapiro.test(residuals(fit.adjr))
qqnorm(residuals(fit.adjr))

#Cp
plot(rs1, scale="Cp", main="Mellow's Cp")
which.min(summary.out$cp) #8
cp.best<-names(summary.out$which[8,])[summary.out$which[8,]][-1]
cp.model <-paste(cp.best,collapse="+")
cp.model <-as.formula(paste("target~",cp.model))

fit.cp <-lm(cp.model, data=student.rm)
summary(fit.cp) #0.6345



List of Articles
번호 제목 글쓴이 날짜 조회 수
공지 우수 코드 게시판 이용 관련 공지사항 DataMarket 2014.05.21 327196
304 투빅스 9&10기 5주차 NLP Basic - 10기 장유영 장유영 2018.08.22 384466
303 투빅스 10기&11기 7주차 NLP - 11기 김유민 file 2019.03.21 362637
302 투빅스 10기&11기 1주차 Algorithm - 11기 한재연 1 file 한재연 2019.01.31 198788
301 투빅스 10기&11기 2주차 SVM, Naive Bayes, KNN - 11기 김대웅 file 김대웅 2019.01.31 147627
» 투빅스 6&7기 2주차 과제 - 회귀분석 6기 장재석 2 재석 2017.02.04 134679
299 투빅스 10&11기 1주차 Logistic Regression - 11기 김대웅 file 김대웅 2019.01.23 117474
298 투빅스 11기&12기 4주차 Decision Tree - 12기 김탁영 file 2019.08.17 116093
297 투빅스 9&10기 4주차 PCA-mnist - 10기 강인구 file kaig 2018.08.16 106225
296 투빅스 7&8기 1주차 과제 알고리즘 - 8기 김강열 file 김강열 2017.07.27 105019
295 SNA(Social Network Analysis) 분석 file 바키똥 2015.04.03 94873
294 투빅스 9&10기 2주차 Naive Bayes - 10기 장유영 2 file 장유영 2018.08.01 91593
293 투빅스 7&8기 6주차 과제 TF-IDF 문서유사도 측정 - 8기 최서현 최서현 2017.08.31 87359
292 인공신경망(Artificial Neural Network) 분석 3 file 권도영 2015.04.13 79820
291 KNN (K-Nearest Neighbor) file 바키똥 2015.09.28 71384
290 능형 회귀 분석 file 자꾸생각나 2015.05.05 65158
289 지도 만들기 file 조호 2015.04.15 63859
288 크롤링 - 전국 이디야 매장정보를 중심으로 (5기 이승은) 2 file 켜져있는멀티탭 2016.03.26 62741
287 인공신경망(Aritificial Neuron Network) file 자꾸생각나 2015.09.16 60039
286 NBA data 회귀분석 / Adult data 로지스틱 회귀분석, 나이브베이즈, 의사결정나무 - 5기 정현재 2 file 정현재 2016.03.03 59822
Board Pagination ‹ Prev 1 2 3 4 5 6 7 8 9 10 ... 16 Next ›
/ 16

나눔글꼴 설치 안내


이 PC에는 나눔글꼴이 설치되어 있지 않습니다.

이 사이트를 나눔글꼴로 보기 위해서는
나눔글꼴을 설치해야 합니다.

설치 취소

Designed by sketchbooks.co.kr / sketchbook5 board skin

Sketchbook5, 스케치북5

Sketchbook5, 스케치북5

Sketchbook5, 스케치북5

Sketchbook5, 스케치북5