(Author notes: Turn cache=TRUE in knitr::opts_chunk() leads to this error. So, just use cache=FALSE for this markdown file)

저자 책 웹페이지: https://dataninja.me/ipds-kr/

R 환경 준비

일단은 필수패키지인 tidyverse, 그리고 NLP를 위한 몇가지 패키지를 로드하자. (로딩 메시지를 감추기 위해 suppressMessages() 명령을 사용.)

# install.packages("tidyverse")
suppressMessages(library(tidyverse))

# install.packages(c("tm", "SnowballC", "wordcloud"))
library(tm)
## Loading required package: NLP
## 
## Attaching package: 'NLP'
## The following object is masked from 'package:ggplot2':
## 
##     annotate
library(SnowballC)
library(wordcloud)
## Loading required package: RColorBrewer

1. (유닉스 명령)

JEOPARDY_CSV.csv 파일에서 유닉스의 cut, sort, uniq 명령을 사용하여 Round와 Category 변수의 도수 분포를 구하라.

Round 도수분포:

$ cut -d ',' -f 3 JEOPARDY_CSV.csv| sort | uniq -c
   1  Round
105912 Double Jeopardy!
3631 Final Jeopardy!
107384 Jeopardy!
   3 Tiebreaker

위 방법의 단점은 첫 줄의 변수이름 (Round)도 출력에 포함된다는 것이다. 하지만 간편히 자료를 살펴보는데는 좋은 방법이다.

Category 도수분포:

Category 변수는 범주가 무척 많기 때문에, 가장 빈도수가 높은 10가지 값만 표현했다. (head -10) 이 방법의 단점은 카테고리가 따옴표 안의 문자열이므로, 쉼표를 포함할 수도 있다는 것이다. 이러한 문제 없이 CSV 파일을 처리하려면 R이나 파이썬의 CSV 파일 처리 라이브러리를 사용해야 한다.

$ cut -d ',' -f 4 JEOPARDY_CSV.csv| sort | uniq -c | sort -n -r | head -10
 547 "BEFORE & AFTER"
 519 "SCIENCE"
 496 "LITERATURE"
 418 "AMERICAN HISTORY"
 401 "POTPOURRI"
 377 "WORLD HISTORY"
 371 "WORD ORIGINS"
 351 "COLLEGES & UNIVERSITIES"
 349 "HISTORY"
 342 "SPORTS"

2. R 스튜디오의 샤이니 단어 구름 예제의 코드를 살펴보자

(https://goo.gl/Dpez2b(http://shiny.rstudio.com/gallery/word-cloud.html)). 여기서 사용된 데이터는 무엇인가? 문서를 다운로드하여 문서에 대한 단어 구름을 그려보자.

server.R 파일의 주석에서 볼 수 있듯이, <한여름밤의 꿈>, <베니스의 상인>, <로미오와 줄리엣> 이다. 우리는 <햄릿>을 사용하도록 하자. http://www.gutenberg.org/cache/epub/1524/pg1524.txt

우선 햄릿 텍스트를 컴퓨터에 다운로드한다:

wget http://www.gutenberg.org/cache/epub/1524/pg1524.txt

R에서 읽어 들인 후, 본문에 설명한 변환을 차례대로 해 준다. 각 처리 이후에 코퍼스의 3144번째 줄이 어떻게 변환되는지 출력해 보았다. (햄릿의 그 유명한 “to be, or not to be…” 독백이다.)

text <- readLines("pg1524.txt", encoding="UTF-8")
corpus <- Corpus(VectorSource(text))
corpus <- tm_map(corpus, content_transformer(tolower))
as.character(corpus[[3144]])
## [1] "to be, or not to be,--that is the question:--"
corpus <- tm_map(corpus, removePunctuation)
as.character(corpus[[3144]])
## [1] "to be or not to bethat is the question"
corpus <- tm_map(corpus, removeNumbers)
as.character(corpus[[3144]])
## [1] "to be or not to bethat is the question"
corpus <- tm_map(corpus, removeWords,
                 c(stopwords('SMART'), "thy", "thou", "thee", "and", "but"))
as.character(corpus[[3144]])
## [1] "     bethat   question"
corpus <- tm_map(corpus, stemDocument)
as.character(corpus[[3144]])
## [1] "bethat question"

위의 출력결과에서 볼 수 있듯이, 처리과정이 개선의 여지가 있다. 예문에서의 ,-- 부분이 통째로 없어져서 bethat 이란 존재하지 않는 단어가 나온 것이 그것이다. 하지만 일단 위의 코퍼스를 사용하도록 하자.

이제 단어구름을 생성할 수 있다:

wordcloud(corpus, max.words=100, random.order=FALSE,
          colors=brewer.pal(8, "Dark2"))