Chapter 11 텍스트 데이터-단어 네트워크맵(1)
- 텍스트 전처리에 사용할 패키지를 불러옵니다.
11.1 DTM by TFIDF
chapter 10 텍스트 분석에서 단어 상관 행렬을 만들었지만, 가중치를 Term Frequency로 했습니다.
이번에는 TF-IDF 가중치를 활용하여 DTM을 만들어서 활용하겠습니다.
지난 시간 DTM을 만들 때 활용했던 동일한 함수를 사용하지만, control 인자에 TFidf를 가중치로 주었고, 숫자로 된 단어를 제외하고 2글자 이상 단어만 사용해서 DTM을 만들어보았습니다.
dtmTfIdf <- DocumentTermMatrix( x = corp, control = list( removeNumbers = TRUE, wordLengths = c(2, Inf), weighting = function(x) weightTfIdf(x, normalize = TRUE) ))
dtmTfIdf
## <<DocumentTermMatrix (documents: 1214, terms: 2014)>>
## Non-/sparse entries: 14538/2430458
## Sparsity : 99%
## Maximal term length: 6
## Weighting : term frequency - inverse document frequency (normalized) (tf-idf)
- dtmTFidf 의 정보를 간략하게 보면 아래와 같습니다.
<<DocumentTermMatrix (documents: 1214, terms: 1901)>>
Non-/sparse entries: 14523/2293291
Sparsity : 99%
Maximal term length: 6
Weighting : term frequency - inverse document frequency (normalized)
1214개의 문서에 X 1,901개 단어 는 2,307,814 칸으로 구성된 DTM을 만든다는 것을 알 수 있습니다.
만들어진 DTM은 1,214개의 문서와 1,901개의 단어 조합으로 이루어졌습니다.
이 조합은 1,214 X 1,901 = 2,307,814개의 값으로 이루어졌다고 보시면 됩니다.Non-/sparse entires는 전체 값 2,307,814개 중 0이 아닌 값이 14,523개 있고, 0인 값이 2,293,291개 있다는 의미입니다. 0이 많은 자료를 희소성(Saprsity)이 있는 자료라고 하며, 네트워크 이론에서 유용하게 활용됩니다. sparsity는 전체 행렬에서 0이 차지하는 비중을 의미합니다.
Maximal term Length는 가장 긴 단어의 경우 6글자로 이루어졌다는 것이며, 가중치는 Normalized tf-idf로 주었다고 보시면 됩니다.
tf-idf 앞에 Normalize 가 붙는 이유는, tf(term-frequency)가 무한대로 발산할 수도 있기 때문입니다. 자세한 내용은 아래 링크 참조 부탁드리며, weigthTfIdf함수는 정규화 방법으로 Boolean frequency 방법을 사용합니다.
11.2 dtm 차원 축소
removeSparseTerms(dtm, sparse 기준)
단어-네트워크 맵을 만들 때는 dtm의 차원을 줄여주는 것이 좋습니다.
차원을 줄여주는 이유는 텍스트 데이터의 차원이 매우 높아, 차원의 저주가 존재하기 때문인데, 더 자세한 내용은 링크나 첨부드린 한국은행에서 발간한 “경제 분석을 위한 텍스트마이닝” 자료를 참고하시면 좋을 것 같습니다.
이제, 작업의 편의를 위해 대부분이 0 값을 가진 것으로 판단할 수 있는 Sparsity 가 0.99가 넘는 열을 삭제해줍니다.
## [1] 1214 2014
dtmTfIdf <- removeSparseTerms(x = dtmTfIdf, sparse = as.numeric(x = 0.99))
# removeSparseTerms 함수를 활용해서 dtmTfIdf에 sparse가 0.99를 넘는 열을 삭제하고, 그것을 다시 dtmTfIdf 로 만들어 달라 는 뜻입니다.
dtmTfIdf
## <<DocumentTermMatrix (documents: 1214, terms: 209)>>
## Non-/sparse entries: 10221/243505
## Sparsity : 96%
## Maximal term length: 4
## Weighting : term frequency - inverse document frequency (normalized) (tf-idf)
11.3 키워드 상관 단어 파악
- 이제 차원이 축소된 dtmTfIdf 가 완성되었고, 내가 원하는 단어와 상관관계가 있는 단어가 무엇인지 findAssocs 함수를 통해 확인해보실 수 있습니다.
findAssocs(x, terms, corlimit)
- 위 함수에 x에는 dtm을 넣으시고, terms에는 원하는 단어, corlimit는 상관계수 몇 이상의 단어를 볼 것인지 넣어주시면 됩니다.
## $조직
## 빠르다 수요일 따르다 문화 직장 칼퇴근
## 0.20 0.16 0.14 0.13 0.11 0.11
## $문화
## 군대 사내 개선 조직 지다
## 0.25 0.18 0.13 0.13 0.10
’조직’과 관련되어 있는 단어 중 상관계수 0.1 이상인 단어를 보여달라고 하니, 빠르다 라는 동사가 상관계수 0.2로 나왔고, 총 5개의 단어가 나왔습니다.
아예 상관행렬을 만들어서, 내가 원하는 키워드와 상관이 있는 단어를 순위대로 보실 수도 있습니다.
11.4 상관행렬 만들기
dtmTfIdf %>% as.matrix() %>% cor() -> corTerms
dtmTfIdf를 매트릭스로 바꿔서 상관계수를 구하는 함수에 넣고, 그 결과를 corTerms로 저장하라는 뜻입니다.
이제 지난 시간에 만든 것처럼, 앞서 만든 dtmTfIdf 를 가지고 단어간 상관행렬을 만들어줍니다.
## num [1:209, 1:209] 1 -0.0271 -0.024 -0.0215 -0.0255 ...
## - attr(*, "dimnames")=List of 2
## ..$ : chr [1:209] "가능" "가다" "가족" "가지다" ...
## ..$ : chr [1:209] "가능" "가다" "가족" "가지다" ...
- 만들어진 단어간 상관행렬 CorTerms를 보시면, 속성(attribute)에 단어들이 들어가있고, 상관계수가 값으로 들어가 있습니다.
11.5 상관 단어 추출
만들어진 상관행렬 CorTerms를 활용하여 특정 단어와 연관된 단어를 추출하는 함수를 작성해보겠습니다.
단어를 입력 받아서, 연관된 단어 10개를 출력하는 함수를 제가 애정하는 나승호님 블로그에서 가져와 봤습니다.
# 키워드 유무를 확인합니다.
checkCorTerms <- function(x,n = 10, keyword) {
# 키워드 유무를 확인합니다.
x %>%
colnames() %>%
str_subset(pattern = keyword) %>%
print()
# 연관 키워드가 있는 컬럼의 전체 단어를 한꺼번에 출력합니다.
corRef <- data.frame()
# 상관계수 높은 순서로 정렬합니다.
corRef <- x[ , keyword] %>%
sort(decreasing = TRUE) %>%
data.frame() %>%
set_colnames(c('corr'))
# 미리보기 합니다.
head(x = corRef, n = n + 1)
}
checkCorTerms(corTerms, 10 ,'문화')
## [1] "문화"
## corr
## 문화 1.00000000
## 군대 0.24615889
## 사내 0.17608346
## 개선 0.13350531
## 조직 0.12682384
## 지다 0.10053374
## 나름 0.09829893
## 발전 0.08455702
## 기업 0.08285898
## 않다 0.06274883
## 보이다 0.06063198
CheckCorTerms() 함수로 문화와 상관관계가 있는 단어 10개를 보니, 앞서 FindAssocs 함수로 확인한 결과와 동일하게 나옵니다.
이제 단어-네트워크맵을 그리기 위한 사전 준비가 마무리되었습니다.