T아카데미에서 R로 하는 텍스트 전처리라는 강의를 들은 후 중요한 내용을 다시 복습해보았다.
강의는 밑의 주소에서 확인할 수 있다.
https://tacademy.skplanet.com/live/player/onlineLectureDetail.action?seq=166
R로 하는 텍스트 전처리 | T아카데미 온라인강의
1. 단정한 데이터란 무엇인지, 텍스트 데이터에서는 어떻게 접목되는지 이해한다. 2. 한글 데이터 분석에 필요한 Rmecabko / KoLNP 사용법을 알아보고, 한글 데이터 전..
tacademy.skplanet.com
1. 네이버 기사 댓글 불러오기
library(N2H4) # https://github.com/forkonlp/N2H4
library(dplyr)
url = "https://news.naver.com/main/ranking/read.nhn?mode=LSD&mid=shm&sid1=001&oid=025&aid=0003068161&rankingType=RANKING"
getAllComment(url) %>%
select(userName, contents, sympathyCount) %>%
arrange(desc(sympathyCount)) -> data
강의에 사용된 기사는 정치관련 기사였는데 1년전 강의라 그런지 삭제된 댓글이 많았다.
그래서 복습용으로 새로운 기사를 가져왔는데 요즘 가장 사회적으로 이슈가 되고 있는 정인이 사건에 대한 기사 댓글을 가져왔다.
library(N2H4)는 강의를 해주신 강사님께서 만드신 라이브러리인데, 네이버 기사를 쉽게 크롤링 할 수 있는 패키지이다. 매우 유용해서 앞으로도 자주 이용할 것 같다.
데이터가 tibble 형식으로 잘 저장된 것을 확인할 수 있다.
2. 텍스트 데이터를 token 단위로 끊어내기
token이란? 글자 중 의미를 가진 단위들을 총칭한다. ex) 자음, 모음, 글자, 형태소, 단어 , n-gram 등등
1) 단어(띄어쓰기) 단위로 끊어내기
- tidytext 패키지의 unnest_tokens()
library(tidytext)
data %>%
unnest_tokens( word, contents, "words") # output, input, token
tidytext 패키지는 단정하게 데이터를 다루어 준다.
따라서 한 행에 한 토큰으로 테이블을 구성한다.
unnest_tokens는 contents에 있는 텍스트 데이터를 "words"(단어, 띄어쓰기) 단위로 끊어내어 word라는 이름의 열에 저장한다는 의미이다.
contents에 들어있던 댓글들이 word라는 열에 token 단위로 분리되어 저장된 것을 확인할 수 있다.
또한 한 행당 토큰 하나로 깔끔하게 들어가 있는 것도 확인할 수 있다.
-
KoNLP 패키지의 extractNoun
KoNLP 패키지란 가장 널리 쓰이는 "형태소 분석기" 이다. 하지만 R이 버젼이 올라간 후 설치가 조금 복잡해져서 install.packages() 구문으로 설치가 불가능하다. 설치는 아래 링크를 참고하면 된다.
KoNLP 설치 이슈 공유 | Facebook
안녕하세요, 현재 코드 내부적인 이슈로 KoNLP 패키지가 cran에서 내려져 있습니다. github 버전으로 설치해야 해서 해당 내용을 공유합니다. (최초 아카이브 버전을 공유했었는데, 설치가 제대로 진
www.facebook.com
library(KoNLP)
df = as.data.frame(data)
word = sapply(df$contents, extractNoun, USE.NAMES = F) # USE.NAMES = T인경우 원문장 같이 출력
word = unlist(word)
KoNLP의 extractNoun 함수를 통해서도 텍스트 데이터를 단어단위로 끊어낼 수 있다.
apply 계열 함수들은 데이터를 받아서 함수를 적용시킨다!!
이때, sapply는 input으로 list or vector를 받아 ouput으로 vector or array(행렬) 형식으로 반환한다.
이때, data는 tibble 형식이므로 sapply의 input 형식에 맞게 데이터프레임으로 변형한 후 적용했다.
결과를 보면 tidytext와 살짝 다른데 tidytext는 띄어쓰기 단위로 끊어냈다면 extractNoun함수는 "명사"만을 추출했기 때문이다.
댓글은 사람이 직접 적은 것이기 때문에 띄어쓰기가 정확하지 않다. 따라서 tidytext를 이용해 띄어쓰기 단위로 텍스트를 끊어내는 것은 댓글에서 단어만 뽑아내기에는 문제가 있다.
또한, KoNLP의 extractNoun은 편리하긴 하지만 생략되는 내용이 많아 정교함이 떨어진다.
따라서 이때 해결방법은 형태소 단위로 텍스트 데이터를 끊어내는 것이다!!
형태소는 의미를 가지는 최소 단위로 체언, 용언, 수식언, 독립언 등등이 있다.(고등학교 국어시간에 열심히 외웠지만 기억이 잘 나지 않는다..ㅎ)
형태소를 token 단위로 사용하면 생략되는 텍스트를 최소화 시켜 좀 더 정교한 전처리가 가능해진다.
2) 형태소 단위로 끊어내기
- KoNLP 패키지의 SimplePos09()
data %>%
unnest_tokens(pos, contents, SimplePos09) %>%
group_by(userName) %>%
mutate(pos_order = 1:n()) -> pos_data # 결과물의 순서보장을 위해서
pos_data를 확인해보면 pos 열에 형태소로 나누어진 텍스트 데이터를 확인할 수 있다.
- 불용어 제거 : stringr 패키지 이용
형태소 단위로 끊어낸 후 가장 먼저 할일은 /n, /e 등과 같은 불용어 등을 제거하는 일이다.또한, 모든 형태소가 필요한것은 아니므로 가장 중요한 체언과 용언만을 남길 것이다./n : 체언, /p : 용언 ( 동사, 형용사 )
- 체언만 남기고 불용어 제거
library(stringr)
pos_data %>%
filter(str_detect(pos, "/n")) %>% # 체언만 찾기
mutate(pos_done = str_remove(pos, "/.*$")) -> n_done
stringr 패키지의 str_detect() 함수를 통해 "/n" 이 속해있는 관측값만 선택했다.그 이후 str_remove() 함수에 정규표현식을 결합하여 "/" 부터 끝까지의 문자를 전부 제거했다.
참고) 정규표현식
- ^ : 이걸로 시작함
- $ : 이걸로 끝남
- . : 임의의 글자 하나
- ? : 앞에 있는 문자가 없거나 하나
- + : 앞에 있는 문자가 하나 이상
- * : 앞에 있는 문자가 없거나 하나 이상
인간/n+으로서/j 를 살펴보면
"/" 부터 끝까지 전부 없애 "인간" 이라는 단어만 남기고 싶다!!
"/.*$"
"/n" 여기서 "/.(임의의 글자하나)" 으로 표시"+/으로서/j" 는 여러개의 문자 이므로 "+(앞에 있는 문자가 하나 이상)" 으로 표시"/n+으로서/j" 로 끝나는 단어 이므로 "$(이걸로 끝남)" 을 의미
이렇게 정리된 데이터를 살펴보면 pos_done 열에 불용어가 제거된 체언들만 남아있는 것을 확인할 수 있다.
- 용언만 남기고 어미를 "다"로 대체
pos_data %>%
filter(str_detect(pos, "/p")) %>%
mutate(pos_done = str_replace_all(pos, "/.*$", "다")) -> p_done
한국어 용언의 어미는 어마어마 하게 많다. 하다, 하는, 하는데, 하면서, 하고... 이를 전부 살리는 건 가지수가 너무 다양해진다.
따라서 stringr 패키지의 str_replace_all() 함수를 이용하여 가장 일반적인 어미 "-다"로 대체했다.
정리된 데이터를 살펴보면, pos_done 열에 용언들이 깔끔하게 정리된 모습을 볼 수 있다.
- pos_done 열을 기준으로 체언 데이터와 용언 데이터 합치기
bind_rows(n_done,p_done) %>%
arrange(desc(sympathyCount)) %>%
filter(nchar(pos_done) > 1) %>%
select(userName, pos_done) -> pos_result # 명사, 동사, 형용사만 남음
bind_rows() 함수는 dplyr 패키지에 속해있는 함수로 행을 기준으로 데이터를 합치는 함수이다.
또한, 형태소가 1글자인 것은 의미가 없을 가능성이 높으므로 사용하지 않았다.
filter 과 nchar(글자수)를 사용하여 글자 수가 1보다 큰 형태소만 선택했다.
따라서 이제 명사, 동사, 형용사만 남은 최종데이터가 만들어졌다.
3. 단어 출현 빈도 계산
pos_result %>%
ungroup() %>% # 사용자별 그룹 해제
count(pos_done, sort = T) %>% # sort = T는 내림차순
View()
dplyr의 count() 함수를 통해 단어의 출현 횟수를 구할 수 있다.
위에서 데이터가 사용자별로 그룹화 되어있었기 때문에 ungroup()을 통해 그룹을 해지했다.
(만약 바로 count() 함수를 적용한다면, 사용자별 단어의 출현 횟수를 구하게 된다.)
4. 워드 클라우드
# wordcloud 설치
library(devtools)
devtools::install_github("lchiffon/wordcloud2")
library(wordcloud2)
# font 불러오기
library(extrafont)
font_import()
loadfonts(device="win")
# 팔레트 불러오기
library(RColorBrewer)
display.brewer.all() # RColorBrewer의 모든 팔레트 볼 수 있음
pal = brewer.pal(9, "Reds") #팔레트에서 사용할 색상 개수, 팔레트명
library(wordcloud2)
wordcloud2(cloud, fontFamily = "YDIYGO330",
color = pal)
워드 클라우드를 통해 정인이 사건에 대한 사람들의 분노를 확인할 수 있었다
다음에는 기사내용을 불러오고 띄어쓰기를 검정하고 동시 출현 빈도로 워드클라우드를 만드는 과정을 기록해볼것이다!!
아직 초보라 워드클라우드 모양도 썩 맘에 들지 않지만 이번 방학동안 차차 해결해가기!!
또 잠깐 강의 후기를 적어보자면 강의는 총 6강으로 이루어져있는데 시간은 짧은 편이다. 하지만 담긴 내용은 매우 알차다.
강사님은 많은 내용을 안가져오셨다고 했지만 강의만 듣고 다 이해하기에는 힘든 내용들도 많았다.(복습이 꼭 필요함!!)
또, dplyr 패키지 내용은 이미 안다는 가정하에 진행되기 때문에 dplyr에 대한 지식은 미리 필요하다.
이렇게 제대로 된 첫 포스팅 끝!! 혹시 잘못된 사항이나 피드백할 사항이 있다면 댓글로 꼭 알려주세요!!
'Data' 카테고리의 다른 글
[python] 네이버 뉴스 기사 작성일, 제목, url 크롤링 ( BeautifulSoup ) (378) | 2021.02.16 |
---|---|
[python] SVM, PCA kaggle 필사 (유방암 데이터) (691) | 2021.02.05 |
[R] 데이터 시각화 with R ( 롤리팝차트 / 덤벨차트 / 슬로프차트 ) (387) | 2021.01.28 |
[R] 데이터 시각화 with R ( 막대그래프/와플차트 ) (384) | 2021.01.26 |
[R] R로 하는 텍스트 전처리2 ( 동시 출현 빈도 / tf-idf/ wordcloud2) (feat. 기리보이) (372) | 2021.01.15 |