(1) R로 카카오톡 텍스트데이터 분석하기
170825.
사람의 말은 그 사람의 인품을 드러내기도 하고, 의식과 무의식을 세상에 내놓는 하나의 수단이다. 그렇다면, 카카오톡에서 우리가 지인들과 아무 생각 없이 하는 말 속에는 내 무의식이 담겨 있지 않을까? 보통 카카오톡에서 어떤 대화를 많이 하는지, 어떤 감정어를 많이 쓰는지 파악하는 것도 재미있을 것 같았다. 마침 멋쟁이사자처럼 동아리에서도 방학 동안 진행해 볼 프로젝트 주제가 필요했다. 그래서 시작한 카카오톡 텍스트데이터 분석.
목표는 두 가지였다.
1. R에서 카카오톡 텍스트데이터를 분석하고 시각화를 해본다.
- 워드클라우드
- 카카오톡 데이터 관련 통계량을 googleVis로 시각화
- 연관성 높은 단어를 qgraph로 시각화
2. R의 코드내용을 Ruby on Rails로 구현한다.
- 웹페이지의 사용자가 카카오톡 대화 txt파일을 제출하면, 분석한 결과를 제공하는 웹페이지 구현.
R에서 필요한 패키지들은 아래와 같았다.
library(qgraph) #연관성 검사 결과값을 시각화하기 위한 그래프.
카카오톡 PC버전에서 '대화 내보내기' 기능으로 txt파일을 추출했다.
데이터 기본 세팅
#1. 톡방 지분 - 누가 더 많이 톡하는가
person1<-length(data[grep("\\[내 이름",data)])
person2<-length(data[grep("\\[상대방 이름",data)]) #내 카톡과 상대 카톡의 개수를 추출했다. 얼마나 많이 떠들었는가 파악할 수 있다. 카톡량<-c(person1,person2) 이름<-c('내 이름','상대방 이름') 카톡지분<-data.frame(이름,카톡량) #데이터프레임 형태로 만듬 pie1<-gvisPieChart(카톡지분,options=list(width=400,height=300)) 이렇게만 실행했을 때, 구글차트에서는 한글이 깨진다. 해결해 보려고 열심히 구글링하다가 찾게 된 해결코드가 아래와 같다. #구글맵 한글깨짐 방지코드 header <- pie1$html$header header <- gsub("charset=utf-8", "charset=euc-kr", header) pie1$html$header <- headerplot(pie1) #파이차트 완성.
완성 결과물. googleVis가 확실히 예쁘다. 사실 ggplot2를 구글링해 찾는 것보다 편해서이기도 했다.
#2. 시간대별 카톡량 분석하기
bfnoon<-data[grep("\\[오전",data)] #오전 데이터값만 불러오기
afnoon<-data[grep("\\[오후",data)] #오후 데이터값만 불러오기 timefunc<-function(x){ time1<-x[grep("\\[[가-힣]+ 1[[:punct:]]",x)] #1시 00분~1시 59분까지 time2<-x[grep("\\[[가-힣]+ 2[[:punct:]]",x)] #2시 00분~2시 59분까지 time3<-x[grep("\\[[가-힣]+ 3[[:punct:]]",x)] time4<-x[grep("\\[[가-힣]+ 4[[:punct:]]",x)] time5<-x[grep("\\[[가-힣]+ 5[[:punct:]]",x)] time6<-x[grep("\\[[가-힣]+ 6[[:punct:]]",x)] time7<-x[grep("\\[[가-힣]+ 7[[:punct:]]",x)] time8<-x[grep("\\[[가-힣]+ 8[[:punct:]]",x)] time9<-x[grep("\\[[가-힣]+ 9[[:punct:]]",x)] time10<-x[grep("\\[[가-힣]+ 10[[:punct:]]",x)] time11<-x[grep("\\[[가-힣]+ 11[[:punct:]]",x)] time12<-x[grep("\\[[가-힣]+ 12[[:punct:]]",x)] return(c(length(time1),length(time2),length(time3), length(time4),length(time5),length(time6),length(time7), length(time8),length(time9),length(time10),length(time11),length(time12))) } #시간대별로 카톡수가 얼마나 되는지 개수 세는 함수. 1시~12시까지의 카톡개수를 return한다. Beforenoon<-timefunc(bfnoon) #오전 시간대별 카톡개수 Afternoon<-timefunc(afnoon) #오후 시간대별 카톡개수 time<-c('1시','2시','3시','4시','5시','6시','7시','8시','9시','10시','11시','12시') beforenoon1<-data.frame(time,Beforenoon,Afternoon) #표 형식으로 만들기 위해서 data.frame형태로 합침. 시간대별차트<- gvisColumnChart(beforenoon1,options=list(height=400,weight=500)) #마찬가지로 한글깨짐방지 header <- 시간대별차트$html$header header <- gsub("charset=utf-8", "charset=euc-kr", header) 시간대별차트$html$header <- header
plot(시간대별차트)
#3. 텍스트분석을 위한 데이터 전처리
텍스트 데이터에서 의미있는 명사들만 파악하기 위한 전처리 과정이다.
의미없는 단어들을 미리 걸러내야 하는데, 어떤 단어가 의미없는 단어인지 미리 생각해야 한다.
head(data_mod)
구어체로 이루어지는 카카오톡 특성상 세 가지 문제가 발생한다.
오탈자와 띄어쓰기, 그리고 줄임말.
정밀하게 분석하려면 오탈자도 전부 바꾸어주어야 한다.
str_replace_all("겟","겠") 처럼 받침에 있는 오타라던지,
str_replace_all("하지말고","하지 말고") 처럼 띄어쓰기 문제가 있는 것들을 전부 바꾸어야 한다.
논문을 쓴다거나 전처리가 정밀해야 하는 경우라면 모든 경우의 수를 고려해야겠지만,
재미로 하는 분석이었으니 이 정도로 끝냈다.
줄임말의 경우는 이렇게 해결했다.
카카오톡에서 많이 쓰는 줄임말이 있다면, 이런 방식으로 사전에 등재하면 된다.
noun <- sapply(data_mod, extractNoun, USE.NAMES=F) %>% unlist() #전처리한 데이터에서 extractNoun함수로 명사만 추출한다. noun2 <- Filter(function(x){nchar(x) >= 2}, noun) #2단어 이상의 명사만 추출 head(noun2) wordFreq <- table(noun2) noundta<-sort(wordFreq, decreasing=TRUE,200) #가장 많이 등장한 단어 순으로 200개 정렬 print(noundta) noundta<-noundta[-1] #앞서 str_replace 때문에 "" 공백이 16000개 정도가 생겨서 가장 많이 등장한 단어 1위다.
그래서 1위 값만 제거했다.
#4. 워드클라우드 만들기
dev.off()
png와 dev.off() 없이 Rstudio로 실행하면 Rstudio에 미리보기 형태로 창이 뜬다.
wordcloud() 내부 명령어
col= 색깔 설정. 위에서 정의한 pal을 그대로 썼다.
cf. 혹시 한글깨짐 현상이 나타난다면,
extrafont와 extrafontdb 라이브러리를 우선 설치해 준 다음
wordcloud(names(noundta),freq=noundta,min.freq=35,random.order=T,rot.per=0,col=pal,family="NanumGothic")
라고 해 주면 해결된다. 나눔고딕 폰트로 워드클라우드를 만들 수 있다.
결과는 이렇게 나온다.
* 단어의 빈출 빈도의 범위에 따라 다른 색으로 표시되게끔 되어 있다.
이를테면 노란색은 150번 이상, 초록색은 70번 이상 80번 미만. 단 어떤 색이 어떤 범주에 들어가는지는 현재까진 나도 모른다.
워드클라우드 결과값. '아무말' 이 1위를 차지했다. 애초에 여기 나열된 단어들에도 아무런 맥락이 없는 것으로 보아 분석은 잘 된 모양이다.
#5. qgraph로 상관성 분석하기.
명사끼리의 연관성 분석, 형용사끼리의 상관성 분석을 따로 진행했다.
(정확히는, 형용사만 있는 것이 아니라 감정이나 느낌을 나타내는 감정어들이다.)
원래 목적은 어떤 명사와 어떤 형용사가 자주 쓰이는지 확인하려 했지만, 너무 어려워서 포기했다.
tt<-paste(unlist(SimplePos22(data_mod))) head(tt,200) SimplePos22 명령어로 텍스트데이터를 명사, 형용사, 부사, 독립언 등등으로 나눈다. #명사만 가져오기 alldta<-str_match_all(tt,"[가-힣]+/[N][C]|[가-힣]+/[N][Q]+")%>% unlist() #형용사만 가져오기 alldta2<-str_match_all(tt,"[가-힣]+/[P][V]+|[가-힣]+/[P][X]+|[가-힣]+/[P][A]+|[가-힣]+/[M][A]+")%>%unlist() N<-str_replace_all(alldta,"/[N][C]","") %>% str_replace_all("/[N][Q]","") %>%unlist() #명사로 추출된 단어들의 분류표인 /NC, /NQ 등을 제거한다. PNM<-str_replace_all(alldta2,"/[P][V]","") %>% str_replace_all("/[P][A]","") %>% str_replace_all("/[M][A]","") %>% str_replace_all("/[P][X]","") %>% unlist()
명사들 상관성분석
DtaCorpusNC<-Corpus(VectorSource(N)) myTdmNC<-TermDocumentMatrix(DtaCorpusNC,control = list(wordLengths=c(4,10), removePunctuation=T,removeNumbers=T,weighting=weightBin)) Encoding(myTdmNC$dimnames$Terms)="UTF-8" #tm패키지에서 제공하는 Corpus를 통해 분류된 단어들의 행렬을 만든다. #Corpus의 원리는 현재 까먹었다. findFreqTerms(myTdmNC, lowfreq=10) #제대로 되었는지 확인 차원에서 입력했다. 제대로 작동했다면 extractnoun함수를 통해 얻은 결과값과 대충 비슷한 형태의 결과가 나온다. mtNC<-as.matrix(myTdmNC) #행렬(matrix)로 변환하는 게 상관성 분석의 핵심이다. mtrowNC<-rowSums(mtNC) mtNC.order<-mtrowNC[order(mtrowNC,decreasing=T)] freq.wordsNC<-sample(mtNC.order[mtNC.order>30],25) freq.wordsNC<-as.matrix(freq.wordsNC) freq.wordsNC
co.matrix<-freq.wordsNC %*% t(freq.wordsNC)
co.matrix를 통해 나온 결과값이 바로
해당 단어가 다른 단어와 얼마나 많이 연결되어 있는지를 나타내는 값이다.
여기서 행렬의 대각선 값은 자기 자신의 값을 두 번 곱한 것인데, 의미있는 결과값이 아니므로 qgraph에서 반영하지 않을 것이다.
vsize=log(diag(co.matrix)*2))
qgraph로 나타낸 연관성분석. 어떤 단어가 어떤 단어와 주로 같이 쓰였는지 선의 굵기로 파악할 수 있다.
형용사(감정어) 상관성분석
명사와 같은 원리이고, 데이터 N을 PNM으로 바꿔서 그대로 실행하면 된다.
co.matrix2<-freq.wordsPNM %*% t(freq.wordsPNM)
vsize=log(diag(co.matrix2)*2))
음, 명사보다는 뭐가 뭔지 파악하기가 좀 더 어렵다.
해놓고 보니,
글 도입부에서 거창하게 말했던 '말 속에 담겨 있는 무의식을 파악한다'는 취지가 무색하다.
제대로 분석을 하기 위해서는 '명사와 감정언 사이의 상관성', '감정어의 긍정, 부정 분석' 등이 더 필요하지만,
제한된 시간과 R 지식의 부족으로 더 진행하지는 못했다. 아쉬움이 남는 부분이다.
'프로그래밍 > 이것저것_개발일지' 카테고리의 다른 글
성균관대학교 학생회 공약 모아보는 웹페이지 제작 프로젝트(2) (0) | 2018.01.21 |
---|---|
성대 학생회 공약 모아보기 사이트 - 멋쟁이사자처럼 프로젝트 (1) (0) | 2018.01.20 |
구글 스프레드시트에서 웹 크롤링하기 - importjson 활용법. (19) | 2017.12.30 |
Aibril 소프트웨어로 아주 쉽게 챗봇 만들어보기 - T아카데미 세미나 (0) | 2017.09.29 |
Rails로 카카오톡 대화 분석 결과를 보여주는 웹페이지 만들기 (0) | 2017.09.27 |