텍스트 마이닝을 통한 SNA

최근 텍스트 마이닝을 통한 SNA 분석이 유행인듯 해서 예제 하나를 공유하고자 한다.

이 예제는 모 대학교 교수님이 코드 얼개를 부탁해서 만들어본 코드 조각이다(도와 드릴 때 공개 가능에 대해서 이미 말씀을 드렸으니 문제 없으리라 본다).

여타 다른 텍스트 마이닝 툴에서 SNA를 하는것의 원리에 대해서는 잘 모르지만 대략 예상을 해보자면 한 문장에서 나오는 단어들의 관계를 연상하면 될거 같다는 생각을 해본다. 그리고 이들간의 관련도 동시성을 SNA그래프를 통해서 표현하면 그만이다.

원리상으로 두 단어 사이의 조건부 확률(confidence), 쌍 출현 확률(support)의 개념으로 보자면 association rule을 활용하면 될 거란 생각을 해본다.

따라서 문장에서 단어들을 추출하기 위해 내가 만든 KoNLP 패키지를 사용하고, arules는 연관분석을 위해 사용한다. 그리고 중요한 SNA 그래프는 igraph 패키지를 통해서 출력한다. 전부터 이야기 했지만 대부분 예상하는 기능을 가지는 패키지는 모두 R에 존재한다고 생각하면 되고 이를 어떻게 적재 적소에 배치해서 활용하는지는 사용자의 몫이다. ^^;

library(KoNLP)
library(arules)
library(igraph)
library(combinat)


f <- file("다문화_utf8.txt", encoding="UTF-8")
fl <- readLines(f)
close(f)
tran <- Map(extractNoun, fl)
tran <- unique(tran)
tran <- sapply(tran, unique)
tran <- sapply(tran, function(x) {Filter(function(y) {nchar(y) <= 4 && nchar(y) > 1 && is.hangul(y)},x)} )
tran <- Filter(function(x){length(x) >= 2}, tran)
names(tran) <- paste("Tr", 1:length(tran), sep="")
wordtran <- as(tran, "transactions")

#co-occurance table
wordtab <- crossTable(wordtran)


ares <- apriori(wordtran, parameter=list(supp=0.05, conf=0.05))
inspect(ares)
rules <- labels(ares, ruleSep=" ")
rules <- sapply(rules, strsplit, " ",  USE.NAMES=F)
rulemat <- do.call("rbind", rules)

# ares <- apriori(wordtran, parameter=list(supp=0.05, conf=0.05))
# inspect(ares)
# rules <- labels(ares, ruleSep="/", setStart="", setEnd="")
# rules <- sapply(rules, strsplit, "/",  USE.NAMES=F)
# rules <- Filter(function(x){!any(x == "")},rules)
# rulemat <- do.call("rbind", rules)
# rulequality <- quality(ares)
# ruleg <- graph.edgelist(rulemat,directed=F)

#plot for important pairs
ruleg <- graph.edgelist(rulemat[-c(1:16),],directed=F)
plot.igraph(ruleg, vertex.label=V(ruleg)$name, vertex.label.cex=0.5, vertex.size=20, layout=layout.fruchterman.reingold.grid)


#plot for all pairs
# tranpairs <- sapply(tran, function(x){t(combn(x,2))})
# sapply(tran,function(x){x })
# edgelist  <- do.call("rbind", tranpairs)
# edgelist <- unique(edgelist)
# g <- graph.edgelist(edgelist, directed=F)
# plot(g)

 

소스 코드는 위와 같다. 입력되는 데이터는 한 라인에 한 문장에 있는 파일이면 된다. 내 경우에는 아래와 같은 내용의 파일을 활용했다.

 > head(fl)
[1] "한국·중국·베트남의 다문화 사회 인식 비교 분석"
[2] "연구논문 : 다문화사회의 법적 기반에 관한 소고 -국제인권법을 중심으로-"
[3] "다문화 공생의 정치원리로서 아렌트주의(Arendtianism)"
[4] "전북지역 다문화가족 어린이의 구강건강 실태조사"
[5] "특집 : 다문화 가정 상담"
[6] "한국 문화 콘텐츠 개발의 필요성과 방향"

 

물론 arules에서 룰 분석을 위해서 co-occurance table을 만들고 이에 대한 코드도 19번째 라인에 있다. 테이블을 보고 싶다면 이를 출력해 보면 된다.

 

 

arules

 

그리고 이런 SNA 결과가 있으면 여러 중심성 측도에 대해서 알아볼 수 있는데, 근접 중심성(closeness)에 대해서 알아보면 아래와 같다.

closen <- closeness(ruleg)
plot(closen, col="red",xaxt="n", lty="solid", type="b", xlab="단어", ylab="closeness")
points(closen, pch=16, col="navy")
axis(1, seq(1, length(closen)), V(ruleg)$name, cex=5)

 

 

closen

 

예상 했던대로 ‘다문화’라는 단어의 중심성이 높게 나타난다. 그리고 관계 중심성(betweenness)을 구해도 역시 크게 다르지 않다. 만일 network star가 두 개 이상 존재한다면 관계 중심성을 알아보는게 더 효과적일 수 있다.

페이지 랭크도 역시 구해볼 수 있지만 네트워크가 작은지라 역시 생략하겠다.

다시 한번 언급하지만, R은 4000여개 가까이 되는 패키지를 어떻게 활용하는지가 관건이며, 그리고 여러 패키지를 유기적으로 연결하기 위해서는 R 문법에 대한 깊이 이는 이해, 플로팅 문법 등 여타 백 그라운드 지식이 필수적이란 생각이 든다.

0 0 votes
Article Rating
Subscribe
Notify of
guest

20 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
MJCHO

이거 예제 파일 받을 수  없나요? 

gogamza

말씀 드렸던 것처럼 파일은 배포하지 않습니다. 아무 텍스트나 가능하니 그것을 활용하시는게 좋습니다. 

박영석

이거 돌려봐도 이상하게 나오던데요?

gogamza

데이터에따라 어떤 전처리가 필요할지 판단하셔서 적용 하셔야 될겁니다..

Juno Kim55

본 소스에 bitops lib(KoNLP 에서 필요로 하네요) 만 추가하여 예제 다문화 파일 그대로  입력하여 돌려봤는데  Plot에서 한글이 제대로 동작하지 않네요(Rstudio사용, UTF-8)
한글 그래픽을 위해서 추가로 해야하는 작업이 있는지요?

gogamza

한글 그래프 출력을 위해서 체크해야 될 부분이 좀 있습니다. 
입출력시 한글이 잘 들어갔는지 확인 해봐야 하고, 폰트가 한글을 지원하는지도 확인해봐야 됩니다.
제가 이 글만 보고는 뭐가 문제인지 파악하기 힘들겠네요. 

Juno Kim55

빠른 답변 감사드려요^^
한글이 잘 들어 갔는지 확인을 거듭 했답니다. 즉 콘솔에서 
> head(fl) 를 실행하면 블로그 내용 그대로 한글 출력됨을 
확인했구요. 음, 그러니까 폰드가 한글을 지원하는거고.혹시 더
확인할 것은 없는지요?

궁금이

초보적인 질문인데요 아래 텍스트 파일을 불러들이는 방법이 무언가요
에러가 발생합니다. 디렉토리만 정해주면되는거 아닌가요?

f <- file("다문화_utf8.txt", encoding="UTF-8")

gogamza

텍스트 파일이 있어셔야 합니다.
저작권 때문에 텍스트 파일은 공유하지 않습니다.

Chad

초보적인 질문입니다만, 위 코드를 실행했을 때, mulemat 변수에 할당되는 데이터가 1225×2로 나타나는데 원인을 모르겠습니다.

앵무새

왜전 readLines() 입력할때 계속 이런 오류가 뜰까요?

경고메시지:

1: 입력 커넥션 ‘c:/rtext/dh.txt’에서 유효하지 않은 입력을 찾았습니다

2: line 1 appears to contain an embedded nul

3: In readLines(f) :

‘c:/rtext/dh.txt’에서 불완전한 마지막 행이 발견되었습니다

gogamza

데이터를 보여주시지 않고서는 원인이 무엇인지 저도 알지 못합니다. ^^;

Youngseok Sim

rulemat <- do.call("rbind", rules)
코드를 코딩하니
In rbind(c("{", "}", " ", "{", "산", "책", "}"), c("{", "}", " ", :
number of columns of result is not a multiple of vector length (arg 1)
다음과 같은 에러가 자꾸 뜹니다ㅠ 해결방법 좀 부탁드립니다ㅠㅠ

그리고
ruleg <- graph.edgelist(rulemat[-c(1:16),],directed=F)
이 코드에서 rulemat 이하가 의미하는 바에 무엇인지도 알고싶습니다.

gogamza

R의 기본 문법에 대해서 이해를 하신 이후에 코드를 살펴보시는걸 추천드립니다. 위와 같은 에러와 코드 설명은 모두 문법 이해 이후에 가능한 부분입니다.

김현영

안녕하세요 고감자님, igraph 관련해서 궁금한 점이 있습니다. 한글텍스트가 섞여있는 그래프에 대해서 plot은 한글이 안깨지고 잘 되는데 이걸 고해상도로 출력하기 위해 cairo_pdf 혹은 pdf(…, type=”Korea1deb”) 등을 사용해 pdf로 출력을 시도할 때 계속 한글이 [] [] [] 이런식으로 네모칸으로 표시가 됩니다. 고감자님께서 써주신 팁을 포함하여 구글링에서 할 수 있는 모든 방법을 시도했지만(어도비 폰트 폴더에 시스템 폰트 복붙 포함) 계속 같은 결과만 나옵니다.

pdf로 출력 시

41: In text.default(x, y, labels = labels, col = label.color, … : conversion failure on ‘?뚯궗’ in ‘mbcsToSbcs’: dot substituted for

42: In text.default(x, y, labels = labels, col = label.color, … : conversion failure on ‘?뚯궗’ in ‘mbcsToSbcs’: dot substituted for

49: In text.default(x, y, labels = labels, col = label.color, … :

유니코드 문자 U+addc에 대한 폰트메트릭을 알 수 없습니다

50: In text.default(x, y, labels = labels, col = label.color, … :

유니코드 문자 U+baa8에 대한 폰트메트릭을 알 수 없습니다

There were 36 warnings (use warnings() to see them)

라는 warning이 나오는 것으로 보아 인코딩 문제인 것 같기도 한데 잘 모르겠습니다.

사용환경은 윈도우, “R version 3.2.2 (2015-08-14)”, R 기본 인코딩은 “UTF-8”, 현재 사용패키지 및 패키지의 로딩 순서는 아래와 같습니다.

(“e1071″,”trend”,”doParallel”, “doBy”, “cluster”, “parallel”, “TTR”,

“forecast”, “plyr”, “dplyr”, “lubridate”,”neuralnet”, “XML”, “RCurl”, “tm”, “wordcloud”,

“httr”, “rvest”, “ggplot2”, “devtools”, “KoNLP”, “arules”, “igraph”, “randomForest”, “C50”)

Changhyeon Woo

경고메시지:

1: 입력 커넥션 ‘c:/rtext/dh.txt’에서 유효하지 않은 입력을 찾았습니다
2: line 1 appears to contain an embedded nul
3: In readLines(f) :
‘d:/cc.txt’에서 불완전한 마지막 행이 발견되었습니다라인 1에서 nul 을 포함하는 것으로 보여집니다

—————————–
혹은

1. 라인 1에서 nul 을 포함하는 것으로 보여집니다

—————————-

데이터를 이리저리 수정해봐도 위 메세지같은 에러가 계속 떠서 분석을 하지못하고있습니다. 혹시 해결방법 알 수 있을까요?

텍스트파일은 드롭박스를 통해 첨부했습니다

https://www.dropbox.com/s/kgvk2desaa6kuz1/cc.txt?dl=0

이전에 다른 작업을 할때도 데이터가 인식되지않아 애를 먹었는데요,
알려주시는 대로 설치, 실행 모두 했는데도 원인을 모르겠네요
워드클라우드로 만드는 작업은 하다보니 성공했는데
다음으로 텍스트마이닝에서 실패중입니다.
해결방법 부탁드리겠습니다

Changhyeon Woo

다른 파일로 SNA 분석을 진행하는 중에

> names(tran) <- paste("Tr", 1:length(tran), sep="")

Error in names(tran) <- paste("Tr", 1:length(tran), sep = "") :

'names' attribute [2] must be the same length as the vector [0]

이런 에러메세지는 어떻게 해결해야할까요?

데이터 주소는 아래남깁니다.
데이터는 한 라인에 한 문장씩있는 영문 데이터파일입니다.
https://www.dropbox.com/s/wepaxc379dz3as8/kkk2.txt?dl=0

Changhyeon Woo

또 다른 파일로 SNA 분석을 진행하는 중 입니다.

이번에는 마지막까지 에러메세지없이 잘 작동하다가

>plot.igraph(ruleg, vertex.label=V(ruleg)$name, vertex.label.cex=0.5, vertex.size=20, layout=layout.fruchterman.reingold.grid)

명령어를 입력하면

—————————————————————————————————–

Error in symbols(x = coords[, 1], y = coords[, 2], bg = vertex.color, :

심볼의 좌표가 유효하지 않습니다

In addition: Warning messages:

1: In v(graph) : Grid Fruchterman-Reingold layout was removed,

we use Fruchterman-Reingold instead.

2: In min(x) : no non-missing arguments to min; returning Inf

3: In max(x) : no non-missing arguments to max; returning -Inf

4: In min(x) : no non-missing arguments to min; returning Inf

5: In max(x) : no non-missing arguments to max; returning -Inf

—————————————————————————————————–

>head(f1)
Error in head(f1) :

함수 ‘head’를 위한 메소드 선택시 인수 ‘x’를 평가하는데 오류가 발생했습니다: Error: object ‘f1’ not found

왜 파일을 열면 목록이 안열리고 이런 에러가 뜨는지 모르겠네요
조언부탁드립니다.

데이터는 한 라인에 한 문장씩 있는 한글 데이터파일입니다.
https://www.dropbox.com/s/kgvk2desaa6kuz1/cc.txt?dl=0

김동남

안녕하세요 제가 이 코드를 써서 돌려보니

Error in names(tran) <- paste("Tr", 1:length(tran), sep = "") :
'names' 속성 [2]는 반드시 벡터 [0]와 같은 길이를 가져야 합니다

라고 나오는데 이런것은 어떻게 해결하는가요?

[…] 텍스트 마이닝을 통한 SNA […]