8주차 수업 시간에 학생 개인은 자신의 연구 프로젝트를 수행하기 위한 계획서를 작성하여 제출하고 (5장 내외) 이에 대한 발표를 진행합니다.
연구계획서의 구성은 다음과 같습니다.
대단위의 텍스트를 컴퓨터로 분석하기 위한 SW는 많이 있지만, 그중에서 R은 “데이터과학”의 영역에서 애용되고 있는 프로그래밍 환경이다. 그 이유는 R이 무료이면서 오픈소스라는 장점과 함께 통계분석을 위해 고안된 SW로서 데이터과학 응용에 적합하기 때문이다. 특히, 오픈소스 프로그래밍 환경을 제공하기 때문에 다양한 목적에 따라 다양한 기능을 수행하는 확장 SW 라이브러리들이 패키지 형태로 모인다는 점은 R의 큰 장점 중 하나이다. 예를 들어, 대표적 패키지 저장소인 “Comprehensive R Archive Network (CRAN)”에는 절차적 적합성과 호환성 검토를 통과한 10,000개 이상의 패키지들이 집적되어 있고, 각각의 패키지는 사용 편의와 유용성을 위해 지속적인 관리를 받는다. 이러한 패키지는 매우 간단하게 R에 설치 후 사용가능하기 때문에 협업 프로젝트에도 적합하다. 특히, R에는 기초적인 문자열 조작부터 감정분석, 토픽모델링까지 다양한 텍스트 분석용 패키지가 50개가 넘게 있다. 또한 rOpenSci는 R 사용자들의 공간으로서 텍스트 분석에 관심있는 연구자과 개발자의 모임이 결성되어 있기 때문에 협력과 도움이 필요할 때도 유용하다. 결국, R을 활용하여 텍스트를 분석하는 것은 사회과학의 영역에서 심도있고 다양한 주제의 연구를 위해 컴퓨터 텍스트 분석을 수행하기 위한 효과적인 수단이다. 이러한 R을 보다 편리하게 이용하기 위해 사용자 친화적 인터페이스인 RStudio 사용을 추천한다.
우선, 각 문서의 디지털 텍스트를 정리해야 할 필요가 있는데, 예를 들어 문자열에 등장하는 불필요한 공란과 구두점 등을 제거해줌으로써 텍스트를 균일한 의미 단위로 분석할 수 있는 준비 과정이 필요하다. 이를 텍스트 전처리 과정이라 한다.
토큰화 과정은 텍스트를 분석의 어휘 등의 기본 단위로 쪼개는 것을 의미한다. 한국어의 경우 형태소 분석 및 품사 태깅 작업이 요구된다. http://konlpy.org/ko/v0.4.4/morph/
토큰화를 거친 텍스트 데이터는 정제와 숫자 변환 및 가중치 부여, 정보 추출 등의 자연어 처리를 거쳐 분류와 유목화, 예측을 위한 알고리즘에 적용한다.
분석 결과를 해석한다.
rJava
패키지 설치가 필요함. multilinguer
패키지의 install_jdk()
이용해 설치.# install.packages("multilinguer")
library(multilinguer)
install_jdk()
은전한닢 프로젝트가 기반으로 하고 있는 mecab은 일본어 형태소 분석기로, 띄어쓰기와 관계없이 형태소를 분석합니다. 인터넷에서 수집한 텍스트는 띄어쓰기에 오류가 있는 경우가 많아, 텍스트 분석을 진행할 때 은전한닢 프로젝트의 mecab-ko를 통해 진행하는 것이 유용할 수 있습니다." by 김준혁 https://www.rdocumentation.org/packages/RcppMeCab/versions/0.0.1.2
#install.packages("RmecabKo")
library(RmecabKo)
RmecabKo::install_mecab("C:/mecab")
#install.packages("RcppMeCab")
library(RcppMeCab)
?pos
pos(iconv("아버지가방에들어가신다", to="utf8"))
spacing("아버지가방에들어가신다")
pos("한국어 텍스트를 컴퓨터로 분석해 봅시다")
pos(iconv("한국어 텍스트를 컴퓨터로 분석해 봅시다", to="utf8"))
RcppMeCab::pos(iconv("한국어 텍스트를 컴퓨터로 분석해 봅시다", to="utf8"))
빅카인즈에서 CSV 형태의 뉴스 데이터를 불러온다.
# 코로나 백신 관련 뉴스: 키워드 검색 - "코로나 + 백신"
# 중앙지, 지역종합지, 방송사
# 지난 6개월 기간
# 제목 혹은 본문에 키워드 포함
# 중복 기사 제거 (분석제외)
# 엑셀파일 다운로드 폴더 확인
getwd()
## [1] "C:/Users/CAU/Dropbox/2021_Class/DM_BD/DM_BD_R"
# 엑셀파일 불러오기
# install.packages("readxl")
library(readxl)
cv <- read_excel("bigkinds_corona_vaccine.xlsx", sheet = 1)
class(cv)
## [1] "tbl_df" "tbl" "data.frame"
cv
## # A tibble: 16,110 x 11
## DATE COMPANY BYLINE HEADLINE PERSON PLACE ORG KEYWORD FEATURE TEXT URL
## <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr>
## 1 20210~ 중부일보~ 중부일보~ "[사설] 고~ <NA> 이스라엘~ 유럽의약~ 고령층,본격~ az,유럽,~ "고령층~ www.~
## 2 20210~ 중앙일보~ 홍주희(h~ "AZ \"코~ <NA> 미국,美~ AP통신~ AZ,코로나~ 아스트라제네~ "아스트~ http~
## 3 20210~ YTN 이은지 "[생생경제]~ 박세리,김~ 주내,미~ 차영,S~ SK,성공,~ 공모주,차영~ "■ 방~ http~
## 4 20210~ YTN 이은지 "[생생경제]~ 우다야 라~ 서울,중~ YTN,~ 코로나의무검~ 노동자,김혜~ "■ 방~ http~
## 5 20210~ 중앙일보~ 황수연(p~ "\"AZ 접~ 나상훈,서~ <NA> 의대,유~ AZ,접종,~ 혈전증,az~ "최근 ~ http~
## 6 20210~ 전남일보~ 서울=김선~ "이용빈, \~ 이용빈,송~ 인도,(~ 정부,세~ 이용빈,폭력~ 미얀마,광주~ "더불어~ http~
## 7 20210~ 동아일보~ 박태근 "“선택적 분~ 유현준,김~ <NA> 목수 선택,분노,~ 김제동,전문~ "방송인~ http~
## 8 20210~ 중앙일보~ 장주영(j~ "김제동 책 ~ 유재석,보~ <NA> <NA> 김제동,욕설~ 김제동,이용~ "방송인~ http~
## 9 20210~ 중앙일보~ 윤성민(y~ "LH 두고 ~ 문재인,문~ 면목,경~ 한국토지~ LH,부동산~ 부동산,지원~ "문재인~ http~
## 10 20210~ YTN 임주영 "[더뉴스] ~ 오세훈,박~ 울산,전~ 국민의당~ 대통령,지지~ 지지율,서울~ "■ 진~ http~
## # ... with 16,100 more rows
cv$HEADLINE[1:10]
## [1] "[사설] 고령층에도 본격화된 AZ 백신 접종"
## [2] "AZ \"코로나백신, \u7f8e 임상서 효과 79% 혈전 위험 증가 없어\""
## [3] "[생생경제] SK바사. 공모주라고 무조건 성공은 아니다. 투자 시 유의할 점"
## [4] "[생생경제] 코로나의무검사보다 근로환경개선이 더 시급(우다야 라이 민주노총 이주노조위원장)"
## [5] "\"AZ 접종 후 희귀 혈전 발생 20대 구급대원 증상 호전돼\""
## [6] "이용빈, \"미얀마 군부 폭력의 희생자에 대한 인도적 지원 시급\""
## [7] "“선택적 분노 김제동 선생” 신간 리뷰 삭제 논란"
## [8] "김제동 책 비판 리뷰 삭제 논란 \"욕설도 아닌데 검열하냐\""
## [9] "LH 두고 \"부동산 적폐\"→\"누적된 관행\" 일주일만에 말바뀐 \u6587"
## [10] "[더뉴스] [리얼미터] 문 대통령 지지율 '최저치'...LH 사태 여파"
class(cv$HEADLINE)
## [1] "character"
length(cv$HEADLINE)
## [1] 16110
뉴스 헤드라인에서 주요하게 등장하는 단어들을 파악하기 위해선, 한국어 문자열을 단어 단위로 구분할 수 있는 형태소 분석을 시행해야 합니다. 형태소란 “일정한 의미가 있는 가장 작은 말의 내에서 따로 떼어낼 수 있는 것으로 더 분석하면 뜻이 없어지는 말의 단위”이다.
하지만 형태소 분석 단계 전에 우선 간단한 전처리를 통해 빈칸을 기준으로 문자열을 쪼개 어떠한 의미가 중요하게 등장하는지를 파악해봅시다.
library(stringr)
str_split(cv$HEADLINE[1:10], " ")
## [[1]]
## [1] "[사설]" "고령층에도" "본격화된" "AZ" "백신"
## [6] "접종"
##
## [[2]]
## [1] "AZ" "\"코로나백신," "\u7f8e" "임상서"
## [5] "효과" "79%" "혈전" "위험"
## [9] "증가" "없어\""
##
## [[3]]
## [1] "[생생경제]" "SK바사." "공모주라고" "무조건" "성공은"
## [6] "아니다." "투자" "시" "유의할" "점"
##
## [[4]]
## [1] "[생생경제]" "코로나의무검사보다" "근로환경개선이"
## [4] "더" "시급(우다야" "라이"
## [7] "민주노총" "이주노조위원장)"
##
## [[5]]
## [1] "\"AZ" "접종" "후" "희귀" "혈전" "발생"
## [7] "20대" "구급대원" "증상" "호전돼\""
##
## [[6]]
## [1] "이용빈," "\"미얀마" "군부" "폭력의" "희생자에" "대한" "인도적"
## [8] "지원" "시급\""
##
## [[7]]
## [1] "“선택적" "분노" "김제동" "선생”" "신간" "리뷰" "삭제"
## [8] "논란"
##
## [[8]]
## [1] "김제동" "책" "비판" "리뷰" "삭제"
## [6] "논란" "\"욕설도" "아닌데" "검열하냐\""
##
## [[9]]
## [1] "LH" "두고" "\"부동산" "적폐\"→\"누적된"
## [5] "관행\"" "" "일주일만에" "말바뀐"
## [9] "\u6587"
##
## [[10]]
## [1] "[더뉴스]" "[리얼미터]" "문" "대통령"
## [5] "지지율" "'최저치'...LH" "사태" "여파"
str_split(cv$HEADLINE[1:10], "\\s+")
## [[1]]
## [1] "[사설]" "고령층에도" "본격화된" "AZ" "백신"
## [6] "접종"
##
## [[2]]
## [1] "AZ" "\"코로나백신," "\u7f8e" "임상서"
## [5] "효과" "79%" "혈전" "위험"
## [9] "증가" "없어\""
##
## [[3]]
## [1] "[생생경제]" "SK바사." "공모주라고" "무조건" "성공은"
## [6] "아니다." "투자" "시" "유의할" "점"
##
## [[4]]
## [1] "[생생경제]" "코로나의무검사보다" "근로환경개선이"
## [4] "더" "시급(우다야" "라이"
## [7] "민주노총" "이주노조위원장)"
##
## [[5]]
## [1] "\"AZ" "접종" "후" "희귀" "혈전" "발생"
## [7] "20대" "구급대원" "증상" "호전돼\""
##
## [[6]]
## [1] "이용빈," "\"미얀마" "군부" "폭력의" "희생자에" "대한" "인도적"
## [8] "지원" "시급\""
##
## [[7]]
## [1] "“선택적" "분노" "김제동" "선생”" "신간" "리뷰" "삭제"
## [8] "논란"
##
## [[8]]
## [1] "김제동" "책" "비판" "리뷰" "삭제"
## [6] "논란" "\"욕설도" "아닌데" "검열하냐\""
##
## [[9]]
## [1] "LH" "두고" "\"부동산" "적폐\"→\"누적된"
## [5] "관행\"" "일주일만에" "말바뀐" "\u6587"
##
## [[10]]
## [1] "[더뉴스]" "[리얼미터]" "문" "대통령"
## [5] "지지율" "'최저치'...LH" "사태" "여파"
str_split(cv$HEADLINE[1:10], "[[:blank:]]+")
## [[1]]
## [1] "[사설]" "고령층에도" "본격화된" "AZ" "백신"
## [6] "접종"
##
## [[2]]
## [1] "AZ" "\"코로나백신," "\u7f8e" "임상서"
## [5] "효과" "79%" "혈전" "위험"
## [9] "증가" "없어\""
##
## [[3]]
## [1] "[생생경제]" "SK바사." "공모주라고" "무조건" "성공은"
## [6] "아니다." "투자" "시" "유의할" "점"
##
## [[4]]
## [1] "[생생경제]" "코로나의무검사보다" "근로환경개선이"
## [4] "더" "시급(우다야" "라이"
## [7] "민주노총" "이주노조위원장)"
##
## [[5]]
## [1] "\"AZ" "접종" "후" "희귀" "혈전" "발생"
## [7] "20대" "구급대원" "증상" "호전돼\""
##
## [[6]]
## [1] "이용빈," "\"미얀마" "군부" "폭력의" "희생자에" "대한" "인도적"
## [8] "지원" "시급\""
##
## [[7]]
## [1] "“선택적" "분노" "김제동" "선생”" "신간" "리뷰" "삭제"
## [8] "논란"
##
## [[8]]
## [1] "김제동" "책" "비판" "리뷰" "삭제"
## [6] "논란" "\"욕설도" "아닌데" "검열하냐\""
##
## [[9]]
## [1] "LH" "두고" "\"부동산" "적폐\"→\"누적된"
## [5] "관행\"" "일주일만에" "말바뀐" "\u6587"
##
## [[10]]
## [1] "[더뉴스]" "[리얼미터]" "문" "대통령"
## [5] "지지율" "'최저치'...LH" "사태" "여파"
str_split(cv$HEADLINE[1:10], "[[:space:]]+")
## [[1]]
## [1] "[사설]" "고령층에도" "본격화된" "AZ" "백신"
## [6] "접종"
##
## [[2]]
## [1] "AZ" "\"코로나백신," "\u7f8e" "임상서"
## [5] "효과" "79%" "혈전" "위험"
## [9] "증가" "없어\""
##
## [[3]]
## [1] "[생생경제]" "SK바사." "공모주라고" "무조건" "성공은"
## [6] "아니다." "투자" "시" "유의할" "점"
##
## [[4]]
## [1] "[생생경제]" "코로나의무검사보다" "근로환경개선이"
## [4] "더" "시급(우다야" "라이"
## [7] "민주노총" "이주노조위원장)"
##
## [[5]]
## [1] "\"AZ" "접종" "후" "희귀" "혈전" "발생"
## [7] "20대" "구급대원" "증상" "호전돼\""
##
## [[6]]
## [1] "이용빈," "\"미얀마" "군부" "폭력의" "희생자에" "대한" "인도적"
## [8] "지원" "시급\""
##
## [[7]]
## [1] "“선택적" "분노" "김제동" "선생”" "신간" "리뷰" "삭제"
## [8] "논란"
##
## [[8]]
## [1] "김제동" "책" "비판" "리뷰" "삭제"
## [6] "논란" "\"욕설도" "아닌데" "검열하냐\""
##
## [[9]]
## [1] "LH" "두고" "\"부동산" "적폐\"→\"누적된"
## [5] "관행\"" "일주일만에" "말바뀐" "\u6587"
##
## [[10]]
## [1] "[더뉴스]" "[리얼미터]" "문" "대통령"
## [5] "지지율" "'최저치'...LH" "사태" "여파"
str_split(cv$HEADLINE[1:10], "[[:space:]]+") %>% unlist()
## [1] "[사설]" "고령층에도" "본격화된"
## [4] "AZ" "백신" "접종"
## [7] "AZ" "\"코로나백신," "\u7f8e"
## [10] "임상서" "효과" "79%"
## [13] "혈전" "위험" "증가"
## [16] "없어\"" "[생생경제]" "SK바사."
## [19] "공모주라고" "무조건" "성공은"
## [22] "아니다." "투자" "시"
## [25] "유의할" "점" "[생생경제]"
## [28] "코로나의무검사보다" "근로환경개선이" "더"
## [31] "시급(우다야" "라이" "민주노총"
## [34] "이주노조위원장)" "\"AZ" "접종"
## [37] "후" "희귀" "혈전"
## [40] "발생" "20대" "구급대원"
## [43] "증상" "호전돼\"" "이용빈,"
## [46] "\"미얀마" "군부" "폭력의"
## [49] "희생자에" "대한" "인도적"
## [52] "지원" "시급\"" "“선택적"
## [55] "분노" "김제동" "선생”"
## [58] "신간" "리뷰" "삭제"
## [61] "논란" "김제동" "책"
## [64] "비판" "리뷰" "삭제"
## [67] "논란" "\"욕설도" "아닌데"
## [70] "검열하냐\"" "LH" "두고"
## [73] "\"부동산" "적폐\"→\"누적된" "관행\""
## [76] "일주일만에" "말바뀐" "\u6587"
## [79] "[더뉴스]" "[리얼미터]" "문"
## [82] "대통령" "지지율" "'최저치'...LH"
## [85] "사태" "여파"
str_split(cv$HEADLINE[1:10], "[[:space:]]+") %>% unlist() %>% table()
## .
## '최저치'...LH "AZ "미얀마 "부동산
## 1 1 1 1
## "욕설도 "코로나백신, [더뉴스] [리얼미터]
## 1 1 1 1
## [사설] [생생경제] “선택적 20대
## 1 2 1 1
## 79% AZ LH SK바사.
## 1 2 1 1
## 검열하냐" 고령층에도 공모주라고 관행"
## 1 1 1 1
## 구급대원 군부 근로환경개선이 김제동
## 1 1 1 2
## 논란 대통령 대한 더
## 2 1 1 1
## 두고 라이 리뷰 말바뀐
## 1 1 2 1
## 무조건 문 \u6587 \u7f8e
## 1 1 1 1
## 민주노총 발생 백신 본격화된
## 1 1 1 1
## 분노 비판 사태 삭제
## 1 1 1 2
## 선생” 성공은 시 시급"
## 1 1 1 1
## 시급(우다야 신간 아니다. 아닌데
## 1 1 1 1
## 없어" 여파 위험 유의할
## 1 1 1 1
## 이용빈, 이주노조위원장) 인도적 일주일만에
## 1 1 1 1
## 임상서 적폐"→"누적된 점 접종
## 1 1 1 2
## 증가 증상 지원 지지율
## 1 1 1 1
## 책 코로나의무검사보다 투자 폭력의
## 1 1 1 1
## 혈전 호전돼" 효과 후
## 2 1 1 1
## 희귀 희생자에
## 1 1
str_split(cv$HEADLINE[1:10], "[[:space:]]+") %>% unlist() %>% table() %>% sort(decreasing=TRUE)
## .
## [생생경제] AZ 김제동 논란
## 2 2 2 2
## 리뷰 삭제 접종 혈전
## 2 2 2 2
## '최저치'...LH "AZ "미얀마 "부동산
## 1 1 1 1
## "욕설도 "코로나백신, [더뉴스] [리얼미터]
## 1 1 1 1
## [사설] “선택적 20대 79%
## 1 1 1 1
## LH SK바사. 검열하냐" 고령층에도
## 1 1 1 1
## 공모주라고 관행" 구급대원 군부
## 1 1 1 1
## 근로환경개선이 대통령 대한 더
## 1 1 1 1
## 두고 라이 말바뀐 무조건
## 1 1 1 1
## 문 \u6587 \u7f8e 민주노총
## 1 1 1 1
## 발생 백신 본격화된 분노
## 1 1 1 1
## 비판 사태 선생” 성공은
## 1 1 1 1
## 시 시급" 시급(우다야 신간
## 1 1 1 1
## 아니다. 아닌데 없어" 여파
## 1 1 1 1
## 위험 유의할 이용빈, 이주노조위원장)
## 1 1 1 1
## 인도적 일주일만에 임상서 적폐"→"누적된
## 1 1 1 1
## 점 증가 증상 지원
## 1 1 1 1
## 지지율 책 코로나의무검사보다 투자
## 1 1 1 1
## 폭력의 호전돼" 효과 후
## 1 1 1 1
## 희귀 희생자에
## 1 1
tokens <- str_split(cv$HEADLINE, "[[:space:]]+") %>% unlist() %>% table() %>% sort(decreasing=TRUE)
tokens[1:300]
## .
## 백신 코로나 접종 코로나19
## 4228 3494 1781 679
## 대통령 문 첫 “코로나
## 601 571 455 436
## \u7f8e 화이자 확진 "코로나
## 429 401 366 362
## 백신, 시작 [사설] 신규
## 298 292 275 271
## 내년 \u6587 치료제 더
## 269 252 234 230
## 정부 방역 백신접종 “백신
## 225 224 223 219
## 것” 확진자 변이 ‘코로나
## 213 208 207 202
## 승인 사망 총리 국민
## 202 201 199 194
## 등 바이든 확보 미국
## 194 192 191 186
## 세계 명 대통령, 모더나
## 179 178 176 175
## "백신 안 확산 추가
## 172 171 168 161
## 수 전 후 것"
## 159 157 156 155
## 개발 이상 \u6587대통령 재난지원금
## 151 151 149 148
## '코로나 국내 중 효과
## 147 147 147 145
## [속보] 아스트라제네카 독감 거리두기
## 143 143 142 140
## 경제 예방접종 다시 트럼프
## 140 139 130 130
## 마스크 만에 대응 정
## 127 126 125 124
## 감염 사망자 4차 미
## 123 118 116 116
## 정세균 또 지원 설
## 114 113 113 112
## 준비 \u82f1 회복 3차
## 110 109 109 108
## '백신 1호 영국 vs
## 107 107 107 104
## 논란 의료진 바이러스 최대
## 103 103 102 102
## 시대 위한 속 올해
## 100 100 99 98
## ‘백신 극복 발표 위기
## 96 96 96 96
## \u91ce 이낙연 한 도입
## 95 94 94 92
## 먼저 [코로나19 맞은 1년
## 92 91 90 89
## 아스트라 하루 못 예산
## 89 88 87 87
## 우려 접종, 정부, 한국
## 87 87 87 86
## 부작용 집단면역 위해 접종"
## 85 85 84 84
## 문재인 듯 계획 공급
## 83 82 81 81
## 오늘 우선 일상 새
## 81 80 80 79
## \u4e2d 무료 \u65e5 2월
## 79 78 78 77
## 대유행 임상 정은경 "코로나19
## 77 77 77 76
## 변종 요양병원 증시 추진
## 76 75 74 74
## 국제뉴스] 유럽 전망 확대
## 73 73 72 72
## 가장 새해 AZ 이후
## 71 71 70 70
## 바이든, 환자 광주 대상
## 69 69 68 68
## 여야 전국 개최 뒤
## 68 68 67 67
## 연휴 "내년 “내년 것
## 67 66 66 66
## 넘어 \u8207 이르면 WHO
## 66 66 66 65
## 국민의힘 유행 검토 두
## 65 65 64 64
## 중국 발생 파우치 할
## 64 63 63 63
## 이어 백신은 \u9751 65세
## 62 61 61 60
## 맞고 문대통령 \u7f8e, 코로나에
## 60 60 60 60
## 2021년 민주당 수도권 없는
## 59 59 59 59
## 영국, 접종” 접종자 [뉴스라이브]
## 59 59 59 58
## [뉴있저] 여야, 연속 코로나로
## 58 58 58 58
## 내달 달 예방 합의
## 56 56 56 56
## 1차 FDA 상황 이인영
## 55 55 55 55
## 3월 집단감염 코스피 러시아
## 54 54 54 53
## 트럼프, 김종인 독감백신 백신도
## 53 52 52 52
## 왜 중단 칼럼] [기고]
## 52 52 52 51
## 내 완료 확산세 K방역
## 51 51 51 50
## 가능성 격상 누적 명분
## 50 50 50 50
## \u6587, 3단계 G20 논의
## 50 49 49 49
## 될 신규확진 접종' 차질
## 49 49 49 49
## 확인 “코로나19 2차 70%
## 49 48 48 48
## 대구 돌파 맞으면 물량
## 48 48 48 48
## 미국, 신년사 안전성 이유
## 48 48 48 48
## 전국민 최초 26일 26일부터
## 48 48 47 47
## 수송 울산 원 전세계
## 47 47 47 47
## 긴급 속도 신청 전남
## 46 46 46 46
## 큰 허가 [더뉴스-더인터뷰] 19
## 46 46 45 45
## 90% 공개 마지막 말
## 45 45 45 45
## 사용 서울시장 역대 연내
## 45 45 45 45
## 우리 곧 내일 때
## 45 44 44 44
## 아직 접종은 협력 /
## 44 44 44 43
## [Mint] [전문] 검사 경고
## 43 43 43 43
## 계약 대전 상승 앞두고
## 43 43 43 43
## 가능" 공방 규모 대선
## 42 42 42 42
## 백신’ 브라질 빨리 새로운
## 42 42 42 42
## 시민 없어” 1년, 2월부터
## 42 42 41 41
## 가짜뉴스 관련 글로벌 방문
## 41 41 41 41
## 비상 언제 예산안 외국인
## 41 41 41 41
## 잘 재확산 총력 추경
## 41 41 41 41
cv$HEADLINE[1:10]
## [1] "[사설] 고령층에도 본격화된 AZ 백신 접종"
## [2] "AZ \"코로나백신, \u7f8e 임상서 효과 79% 혈전 위험 증가 없어\""
## [3] "[생생경제] SK바사. 공모주라고 무조건 성공은 아니다. 투자 시 유의할 점"
## [4] "[생생경제] 코로나의무검사보다 근로환경개선이 더 시급(우다야 라이 민주노총 이주노조위원장)"
## [5] "\"AZ 접종 후 희귀 혈전 발생 20대 구급대원 증상 호전돼\""
## [6] "이용빈, \"미얀마 군부 폭력의 희생자에 대한 인도적 지원 시급\""
## [7] "“선택적 분노 김제동 선생” 신간 리뷰 삭제 논란"
## [8] "김제동 책 비판 리뷰 삭제 논란 \"욕설도 아닌데 검열하냐\""
## [9] "LH 두고 \"부동산 적폐\"→\"누적된 관행\" 일주일만에 말바뀐 \u6587"
## [10] "[더뉴스] [리얼미터] 문 대통령 지지율 '최저치'...LH 사태 여파"
str_replace_all(cv$HEADLINE[1:10], "[[:punct:]]", " ")
## [1] " 사설 고령층에도 본격화된 AZ 백신 접종"
## [2] "AZ 코로나백신 \u7f8e 임상서 효과 79 혈전 위험 증가 없어 "
## [3] " 생생경제 SK바사 공모주라고 무조건 성공은 아니다 투자 시 유의할 점"
## [4] " 생생경제 코로나의무검사보다 근로환경개선이 더 시급 우다야 라이 민주노총 이주노조위원장 "
## [5] " AZ 접종 후 희귀 혈전 발생 20대 구급대원 증상 호전돼 "
## [6] "이용빈 미얀마 군부 폭력의 희생자에 대한 인도적 지원 시급 "
## [7] " 선택적 분노 김제동 선생 신간 리뷰 삭제 논란"
## [8] "김제동 책 비판 리뷰 삭제 논란 욕설도 아닌데 검열하냐 "
## [9] "LH 두고 부동산 적폐 → 누적된 관행 일주일만에 말바뀐 \u6587"
## [10] " 더뉴스 리얼미터 문 대통령 지지율 최저치 LH 사태 여파"
unlist(str_extract_all(cv$HEADLINE[1:1000], "\\[코로나19.+|.+칼럼\\]"))
## [1] "[코로나19 국제뉴스] 고개 드는 ‘자국 중심’ ‘하나의 유럽’ 약화"
## [2] "[코로나19 국제뉴스] 봉쇄 1년, 못 막은 3차 유행 유럽 정치지형 ‘흔들’"
## [3] "[전문인칼럼]"
## [4] "[김의도 칼럼]"
## [5] "[사이언스칼럼]"
## [6] "[코로나19] 충청권 1분기 백신 접종 순조 코로나 신규 확진자 4개 시도 15명"
## [7] "[코로나19 국제뉴스] “코로나19 백신접종 임산부, 아기에게도 항체 생겨”"
## [8] "[코로나19] 대전 화이자 이틀차 974명 접종 충남 당진서 7명 신규 확진"
## [9] "[수요칼럼]"
## [10] "[코로나19 국제뉴스] 모더나, 생후 6개월~11세 어린이 대상 백신 임상 착수"
## [11] "[이철호 칼럼]"
## [12] "[코로나19] 대전 세종 화이자 첫 접종 충청권 확진자는 9명 추가"
## [13] "[코로나19 국제뉴스] \u7f8e 접종소에 울려 퍼진 ‘요요마’의 즉석 연주회"
## [14] "[코로나19] 밤사이 대전 양성 1명 추가 전국 확진자 75% 수도권"
## [15] "[코로나19 극복 무등일보가 함께 <U+2789>] '벼랑 끝' 영세 자영업자"
## [16] "[코로나19 국제뉴스] \u7f8e 전직 대통령들 함께 뭉쳐 “백신 맞읍시다” 광고"
## [17] "[강우일 칼럼]"
## [18] "[코로나19 국제뉴스] EU-영국 코로나19 백신 수출 놓고 또 갈등"
## [19] "[코로나19 국제뉴스] 칠레, 백신접종 속도 이스라엘 제치고 세계 1위"
## [20] "[문화\u4eba칼럼]"
# 대괄호 코너명부터 처리
str_replace_all(cv$HEADLINE[1:10], "\\[[[:word:]& ]+\\]", " ")
## [1] " 고령층에도 본격화된 AZ 백신 접종"
## [2] "AZ \"코로나백신, \u7f8e 임상서 효과 79% 혈전 위험 증가 없어\""
## [3] " SK바사. 공모주라고 무조건 성공은 아니다. 투자 시 유의할 점"
## [4] " 코로나의무검사보다 근로환경개선이 더 시급(우다야 라이 민주노총 이주노조위원장)"
## [5] "\"AZ 접종 후 희귀 혈전 발생 20대 구급대원 증상 호전돼\""
## [6] "이용빈, \"미얀마 군부 폭력의 희생자에 대한 인도적 지원 시급\""
## [7] "“선택적 분노 김제동 선생” 신간 리뷰 삭제 논란"
## [8] "김제동 책 비판 리뷰 삭제 논란 \"욕설도 아닌데 검열하냐\""
## [9] "LH 두고 \"부동산 적폐\"→\"누적된 관행\" 일주일만에 말바뀐 \u6587"
## [10] " 문 대통령 지지율 '최저치'...LH 사태 여파"
str_replace_all(unlist(str_extract_all(cv$HEADLINE[1:1000], "\\[코로나19.+|.+칼럼\\]")), "\\[[[:word:]& ]+\\]", " ")
## [1] " 고개 드는 ‘자국 중심’ ‘하나의 유럽’ 약화"
## [2] " 봉쇄 1년, 못 막은 3차 유행 유럽 정치지형 ‘흔들’"
## [3] " "
## [4] " "
## [5] " "
## [6] " 충청권 1분기 백신 접종 순조 코로나 신규 확진자 4개 시도 15명"
## [7] " “코로나19 백신접종 임산부, 아기에게도 항체 생겨”"
## [8] " 대전 화이자 이틀차 974명 접종 충남 당진서 7명 신규 확진"
## [9] " "
## [10] " 모더나, 생후 6개월~11세 어린이 대상 백신 임상 착수"
## [11] " "
## [12] " 대전 세종 화이자 첫 접종 충청권 확진자는 9명 추가"
## [13] " \u7f8e 접종소에 울려 퍼진 ‘요요마’의 즉석 연주회"
## [14] " 밤사이 대전 양성 1명 추가 전국 확진자 75% 수도권"
## [15] "[코로나19 극복 무등일보가 함께 <U+2789>] '벼랑 끝' 영세 자영업자"
## [16] " \u7f8e 전직 대통령들 함께 뭉쳐 “백신 맞읍시다” 광고"
## [17] " "
## [18] " EU-영국 코로나19 백신 수출 놓고 또 갈등"
## [19] " 칠레, 백신접종 속도 이스라엘 제치고 세계 1위"
## [20] " "
# 구두점 제거
hl <- cv$HEADLINE[1:1000]
str_replace_all(unlist(str_extract_all(hl[1:1000], "\\[코로나19.+|.+칼럼\\]")), "\\[[[:word:]& ]+\\]", " ")
## [1] " 고개 드는 ‘자국 중심’ ‘하나의 유럽’ 약화"
## [2] " 봉쇄 1년, 못 막은 3차 유행 유럽 정치지형 ‘흔들’"
## [3] " "
## [4] " "
## [5] " "
## [6] " 충청권 1분기 백신 접종 순조 코로나 신규 확진자 4개 시도 15명"
## [7] " “코로나19 백신접종 임산부, 아기에게도 항체 생겨”"
## [8] " 대전 화이자 이틀차 974명 접종 충남 당진서 7명 신규 확진"
## [9] " "
## [10] " 모더나, 생후 6개월~11세 어린이 대상 백신 임상 착수"
## [11] " "
## [12] " 대전 세종 화이자 첫 접종 충청권 확진자는 9명 추가"
## [13] " \u7f8e 접종소에 울려 퍼진 ‘요요마’의 즉석 연주회"
## [14] " 밤사이 대전 양성 1명 추가 전국 확진자 75% 수도권"
## [15] "[코로나19 극복 무등일보가 함께 <U+2789>] '벼랑 끝' 영세 자영업자"
## [16] " \u7f8e 전직 대통령들 함께 뭉쳐 “백신 맞읍시다” 광고"
## [17] " "
## [18] " EU-영국 코로나19 백신 수출 놓고 또 갈등"
## [19] " 칠레, 백신접종 속도 이스라엘 제치고 세계 1위"
## [20] " "
str_replace_all(cv$HEADLINE[1:10], "[[:punct:]]", " ")
## [1] " 사설 고령층에도 본격화된 AZ 백신 접종"
## [2] "AZ 코로나백신 \u7f8e 임상서 효과 79 혈전 위험 증가 없어 "
## [3] " 생생경제 SK바사 공모주라고 무조건 성공은 아니다 투자 시 유의할 점"
## [4] " 생생경제 코로나의무검사보다 근로환경개선이 더 시급 우다야 라이 민주노총 이주노조위원장 "
## [5] " AZ 접종 후 희귀 혈전 발생 20대 구급대원 증상 호전돼 "
## [6] "이용빈 미얀마 군부 폭력의 희생자에 대한 인도적 지원 시급 "
## [7] " 선택적 분노 김제동 선생 신간 리뷰 삭제 논란"
## [8] "김제동 책 비판 리뷰 삭제 논란 욕설도 아닌데 검열하냐 "
## [9] "LH 두고 부동산 적폐 → 누적된 관행 일주일만에 말바뀐 \u6587"
## [10] " 더뉴스 리얼미터 문 대통령 지지율 최저치 LH 사태 여파"
# 한자 처리
cv$HEADLINE[1:10]
## [1] "[사설] 고령층에도 본격화된 AZ 백신 접종"
## [2] "AZ \"코로나백신, \u7f8e 임상서 효과 79% 혈전 위험 증가 없어\""
## [3] "[생생경제] SK바사. 공모주라고 무조건 성공은 아니다. 투자 시 유의할 점"
## [4] "[생생경제] 코로나의무검사보다 근로환경개선이 더 시급(우다야 라이 민주노총 이주노조위원장)"
## [5] "\"AZ 접종 후 희귀 혈전 발생 20대 구급대원 증상 호전돼\""
## [6] "이용빈, \"미얀마 군부 폭력의 희생자에 대한 인도적 지원 시급\""
## [7] "“선택적 분노 김제동 선생” 신간 리뷰 삭제 논란"
## [8] "김제동 책 비판 리뷰 삭제 논란 \"욕설도 아닌데 검열하냐\""
## [9] "LH 두고 \"부동산 적폐\"→\"누적된 관행\" 일주일만에 말바뀐 \u6587"
## [10] "[더뉴스] [리얼미터] 문 대통령 지지율 '최저치'...LH 사태 여파"
cv$HEADLINE[7]
## [1] "“선택적 분노 김제동 선생” 신간 리뷰 삭제 논란"
RcppMeCab::pos(cv$HEADLINE[7])
## $`“선택적 분노 김제동 선생” 신간 리뷰 삭제 논란`
## [1] "“/SSO" "선택/NNG" "적/XSN" "분노/NNG" "김제동/NNP"
## [6] "선생/NNG" "”/SSC" "신간/NNP" "리뷰/NNP" "삭제/NNG"
## [11] "논란/NNG"
dim(cv)
## [1] 16110 11
RcppMeCab::pos(cv$HEADLINE) %>%
unlist() %>%
paste(collapse=" ") %>%
str_extract_all(pattern = "[가-힣]+[/]N") %>%
unlist() %>%
paste(collapse=" ") %>%
str_remove_all(pattern="[/]N") %>%
str_split(pattern=" ") %>%
unlist() %>%
table() %>%
sort(decreasing=T) %>%
head()
## .
## 백신 코로나 접종 명 대통령 만
## 6522 6498 3471 1737 1205 1066
지금부터 tibble이라는 데이터 프레임의 형식으로 이루어진 뉴스기사 데이터를 텍스트 분석을 위한 전처리 방식에 대해서 알아보도록 하겠습니다. 이를 위해 필요한 함수를 제공하는 tidyverse 패키지에 대해서 살펴보도록 하겠습니다.
우선, tidyverse패키지의 함수들을 이용해서 트위터 데이터를 처리하는 방법을 알아보도록 하겠습니다. 우선, tidyverse 패키지를 R세션에 설치해 봅시다.
#install.packages(tidyverse")
library(tidyverse)
## -- Attaching packages --------------------------------------- tidyverse 1.3.0 --
## √ ggplot2 3.3.3 √ purrr 0.3.4
## √ tibble 3.1.0 √ dplyr 1.0.4
## √ tidyr 1.1.2 √ forcats 0.5.1
## √ readr 1.3.1
## -- Conflicts ------------------------------------------ tidyverse_conflicts() --
## x dplyr::filter() masks stats::filter()
## x dplyr::lag() masks stats::lag()
첫번째로 살펴 볼 dplyr 패키지의 함수는 select()
입니다. 이 함수는 데이터의 변수를 선택해서 해당 변수만 남기고 나머지 변수들은 제거하는 기능을 합니다. 예를 들어서, 우리의 데이터 객체인 cv
는 11개의 변수로 구성이 되어있죠. 앞서 말했듯, 이 변수들은 우리가 모은 기사들의 성격을 규정하는 역할을 합니다. 예를 들어서, 첫번째 변수의 이름을 DATE
이고 이 변수에는 각 기사의 날짜가 문자 벡터 형태로 포함되어 있습니다.
# 데이터의 변수 선택은: 데이터 객체 이름에 Dollar 사인 후 변수 이름 입력
class(cv$DATE) # 문자 벡터
## [1] "character"
cv$DATE[1:10] # 첫번째 기사부터 열번째 기사의 날짜 정보보 인덱싱
## [1] "20210322" "20210322" "20210322" "20210322" "20210322" "20210322"
## [7] "20210322" "20210322" "20210322" "20210322"
cv 데이터는 11개의 변수로 구성되어 있고, 여기에서 우리가 필요한 변수 중 하나는 HEADLINE
입니다. 이 변수에는 각 기사의 제목, 즉 우리가 분석할 어휘들로 구성된 뉴스 헤드라인이 문자열 벡터 형태로 포함되어 있습니다. 또, 언론사 정보 “COMPANY”와, 날짜 “DATE”, 리드(기사의 첫 200자) “TEXT” 등이 우리가 필요한 기사 정보들이라 할 수 있겠네요.
이 변수들만 남기고 나머지 변수들을 제거하기 위해서 필요한 함수가 바로 select()
입니다.
select()
: 데이터의 변수(들)을 선택 및 처리dim(cv)
## [1] 16110 11
class(cv$HEADLINE) #문자(열) 벡터
## [1] "character"
cv$HEADLINE[1:10] # 첫번째 기사부터 열번째 기사의 문자열 내용 인덱싱
## [1] "[사설] 고령층에도 본격화된 AZ 백신 접종"
## [2] "AZ \"코로나백신, \u7f8e 임상서 효과 79% 혈전 위험 증가 없어\""
## [3] "[생생경제] SK바사. 공모주라고 무조건 성공은 아니다. 투자 시 유의할 점"
## [4] "[생생경제] 코로나의무검사보다 근로환경개선이 더 시급(우다야 라이 민주노총 이주노조위원장)"
## [5] "\"AZ 접종 후 희귀 혈전 발생 20대 구급대원 증상 호전돼\""
## [6] "이용빈, \"미얀마 군부 폭력의 희생자에 대한 인도적 지원 시급\""
## [7] "“선택적 분노 김제동 선생” 신간 리뷰 삭제 논란"
## [8] "김제동 책 비판 리뷰 삭제 논란 \"욕설도 아닌데 검열하냐\""
## [9] "LH 두고 \"부동산 적폐\"→\"누적된 관행\" 일주일만에 말바뀐 \u6587"
## [10] "[더뉴스] [리얼미터] 문 대통령 지지율 '최저치'...LH 사태 여파"
cv %>% select(DATE, COMPANY, HEADLINE, TEXT) # 데이터 처리 과정을 연쇄적으로 이어주는 파이프(pipe) 연산자; cv에서 다음의 변수들만 남기고 나머지는 제거
## # A tibble: 16,110 x 4
## DATE COMPANY HEADLINE TEXT
## <chr> <chr> <chr> <chr>
## 1 202103~ 중부일보~ "[사설] 고령층에도 본격화된 AZ 백신 접종"~ "고령층에 대해 접종이 유보됐던 아스트라제네카(AZ~
## 2 202103~ 중앙일보~ "AZ \"코로나백신, 美 임상서 효과 79% 혈전 위~ "아스트라제네카(AZ)가 미국에서 진행한 신종 코로~
## 3 202103~ YTN "[생생경제] SK바사. 공모주라고 무조건 성공은 아니~ "■ 방송 : YTN 라디오 FM 94.5 (15:~
## 4 202103~ YTN "[생생경제] 코로나의무검사보다 근로환경개선이 더 시급~ "■ 방송 : YTN 라디오 FM 94.5 (15:~
## 5 202103~ 중앙일보~ "\"AZ 접종 후 희귀 혈전 발생 20대 구급대원 증~ "최근 아스트라제네카(AZ) 백신을 접종한 후 희귀~
## 6 202103~ 전남일보~ "이용빈, \"미얀마 군부 폭력의 희생자에 대한 인도적~ "더불어민주당 이용빈(광주 광산구갑) 의원은 22일~
## 7 202103~ 동아일보~ "“선택적 분노 김제동 선생” 신간 리뷰 삭제 논란"~ "방송인 김제동(47)의 신간 ‘질문이 답이 되는 ~
## 8 202103~ 중앙일보~ "김제동 책 비판 리뷰 삭제 논란 \"욕설도 아닌데 검~ "방송인 김제동이 2년여 만에 신간을 출간하며 공식~
## 9 202103~ 중앙일보~ "LH 두고 \"부동산 적폐\"→\"누적된 관행\" ~ "문재인 대통령은 22일 청와대에서 열린 수석보좌관~
## 10 202103~ YTN "[더뉴스] [리얼미터] 문 대통령 지지율 '최저치'.~ "■ 진행 : 강진원 앵커, 박상연 앵커 \r\n■~
## # ... with 16,100 more rows
cv_frames <- cv %>% select(DATE, COMPANY, HEADLINE, TEXT) # 위 처리 과정을 거친 데이터를 cv_text라는 새로운 객체에 할당
dim(cv_frames) # 새로운 데이터 프레임 구조 확인
## [1] 16110 4
filter()
: 데이터의 기사(observation)를 선택 및 처리기사 데이터를 처리하는데 있어, 특정 관측치를 선택할 필요 filter()
함수는 입력된 조건에 부합하는 행들만 남기고 나머지는 지워주는 역할을 합니다. 가령, 어떤 기사의 텍스트에 특정 단어가 포함되어 있는지 여부에 따라 해당 기사만 출력하기 위해 필요한 함수는: str_detect()
- 해당 벡터의 값 중 원하는 문자열이 포함되어 있는지 아닌지 판별하는 기능
library(stringr)
cv_frames %>% filter(str_detect(HEADLINE, "코로나")) %>% dim()
## [1] 6445 4
cv_frames %>% filter(str_detect(HEADLINE, "백신")) %>% dim()
## [1] 6375 4
만약 해당 문자열을 포함하지 않는 기사를 추출하기 위해 필요한 연산자는: !
! 는 논리 연산에서 부정의 뜻을 의미: ~~이 아니다.
cv_frames %>% filter(!str_detect(HEADLINE, regex("AZ", ignore_case = T)))
## # A tibble: 15,962 x 4
## DATE COMPANY HEADLINE TEXT
## <chr> <chr> <chr> <chr>
## 1 202103~ YTN "[생생경제] SK바사. 공모주라고 무조건 성공은 아니~ "■ 방송 : YTN 라디오 FM 94.5 (15:~
## 2 202103~ YTN "[생생경제] 코로나의무검사보다 근로환경개선이 더 시급~ "■ 방송 : YTN 라디오 FM 94.5 (15:~
## 3 202103~ 전남일보~ "이용빈, \"미얀마 군부 폭력의 희생자에 대한 인도적~ "더불어민주당 이용빈(광주 광산구갑) 의원은 22일~
## 4 202103~ 동아일보~ "“선택적 분노 김제동 선생” 신간 리뷰 삭제 논란"~ "방송인 김제동(47)의 신간 ‘질문이 답이 되는 ~
## 5 202103~ 중앙일보~ "김제동 책 비판 리뷰 삭제 논란 \"욕설도 아닌데 검~ "방송인 김제동이 2년여 만에 신간을 출간하며 공식~
## 6 202103~ 중앙일보~ "LH 두고 \"부동산 적폐\"→\"누적된 관행\" ~ "문재인 대통령은 22일 청와대에서 열린 수석보좌관~
## 7 202103~ YTN "[더뉴스] [리얼미터] 문 대통령 지지율 '최저치'.~ "■ 진행 : 강진원 앵커, 박상연 앵커 \r\n■~
## 8 202103~ 한겨레 "혈압약 드시는 80대 아버지, 코로나 백신 맞아도 되~ "전문가 자문을 거쳐 코로나19 백신에 대한 궁금증~
## 9 202103~ 중앙일보~ "확진 1만→200명대 집단면역 다가선 이스라엘, 거~ "국민 절반이 코로나19 접종을 마친 이스라엘에서 ~
## 10 202103~ 대구일보~ "한무경, “전기요금 상승하면 산업계 전반 치명타”"~ "전기요금이 상승할 경우 산업계 전반이 치명타를 입~
## # ... with 15,952 more rows
text 변수에 문자열 벡터로 담겨있는 텍스트 내용이 “코로나”, “우한” 또는 “중국” 문자열 포함하는 조건에 해당하는 행만 남기고 나머지는 제거
dim(cv_frames)
## [1] 16110 4
?duplicated
## starting httpd help server ... done
table(duplicated(cv_frames$HEADLINE))
##
## FALSE TRUE
## 15890 220
cv_frames %>% filter(!duplicated(HEADLINE)) %>% dim()
## [1] 15890 4
cv_frames_unique <- cv_frames %>% filter(!duplicated(HEADLINE))
dim(cv_frames_unique)
## [1] 15890 4
cv_frames_unique$HEADLINE[1:10]
## [1] "[사설] 고령층에도 본격화된 AZ 백신 접종"
## [2] "AZ \"코로나백신, \u7f8e 임상서 효과 79% 혈전 위험 증가 없어\""
## [3] "[생생경제] SK바사. 공모주라고 무조건 성공은 아니다. 투자 시 유의할 점"
## [4] "[생생경제] 코로나의무검사보다 근로환경개선이 더 시급(우다야 라이 민주노총 이주노조위원장)"
## [5] "\"AZ 접종 후 희귀 혈전 발생 20대 구급대원 증상 호전돼\""
## [6] "이용빈, \"미얀마 군부 폭력의 희생자에 대한 인도적 지원 시급\""
## [7] "“선택적 분노 김제동 선생” 신간 리뷰 삭제 논란"
## [8] "김제동 책 비판 리뷰 삭제 논란 \"욕설도 아닌데 검열하냐\""
## [9] "LH 두고 \"부동산 적폐\"→\"누적된 관행\" 일주일만에 말바뀐 \u6587"
## [10] "[더뉴스] [리얼미터] 문 대통령 지지율 '최저치'...LH 사태 여파"
mutate()
: 기존 변수를 이용하여 생성한 새로운 변수를 데이터 열에 추가cv_frames_unique
## # A tibble: 15,890 x 4
## DATE COMPANY HEADLINE TEXT
## <chr> <chr> <chr> <chr>
## 1 202103~ 중부일보~ "[사설] 고령층에도 본격화된 AZ 백신 접종"~ "고령층에 대해 접종이 유보됐던 아스트라제네카(AZ~
## 2 202103~ 중앙일보~ "AZ \"코로나백신, 美 임상서 효과 79% 혈전 위~ "아스트라제네카(AZ)가 미국에서 진행한 신종 코로~
## 3 202103~ YTN "[생생경제] SK바사. 공모주라고 무조건 성공은 아니~ "■ 방송 : YTN 라디오 FM 94.5 (15:~
## 4 202103~ YTN "[생생경제] 코로나의무검사보다 근로환경개선이 더 시급~ "■ 방송 : YTN 라디오 FM 94.5 (15:~
## 5 202103~ 중앙일보~ "\"AZ 접종 후 희귀 혈전 발생 20대 구급대원 증~ "최근 아스트라제네카(AZ) 백신을 접종한 후 희귀~
## 6 202103~ 전남일보~ "이용빈, \"미얀마 군부 폭력의 희생자에 대한 인도적~ "더불어민주당 이용빈(광주 광산구갑) 의원은 22일~
## 7 202103~ 동아일보~ "“선택적 분노 김제동 선생” 신간 리뷰 삭제 논란"~ "방송인 김제동(47)의 신간 ‘질문이 답이 되는 ~
## 8 202103~ 중앙일보~ "김제동 책 비판 리뷰 삭제 논란 \"욕설도 아닌데 검~ "방송인 김제동이 2년여 만에 신간을 출간하며 공식~
## 9 202103~ 중앙일보~ "LH 두고 \"부동산 적폐\"→\"누적된 관행\" ~ "문재인 대통령은 22일 청와대에서 열린 수석보좌관~
## 10 202103~ YTN "[더뉴스] [리얼미터] 문 대통령 지지율 '최저치'.~ "■ 진행 : 강진원 앵커, 박상연 앵커 \r\n■~
## # ... with 15,880 more rows
names(cv_frames_unique)
## [1] "DATE" "COMPANY" "HEADLINE" "TEXT"
cv_frames_unique$DATE[1:10]
## [1] "20210322" "20210322" "20210322" "20210322" "20210322" "20210322"
## [7] "20210322" "20210322" "20210322" "20210322"
library(lubridate) # 날짜 정보를 다루기 위한 함수를 제공
##
## Attaching package: 'lubridate'
## The following objects are masked from 'package:base':
##
## date, intersect, setdiff, union
cv_frames_unique %>% mutate(date = ymd(DATE))
## # A tibble: 15,890 x 5
## DATE COMPANY HEADLINE TEXT date
## <chr> <chr> <chr> <chr> <date>
## 1 20210~ 중부일보 "[사설] 고령층에도 본격화된 AZ 백신 접종~ "고령층에 대해 접종이 유보됐던 아스트라~ 2021-03-22
## 2 20210~ 중앙일보 "AZ \"코로나백신, 美 임상서 효과 79%~ "아스트라제네카(AZ)가 미국에서 진행한~ 2021-03-22
## 3 20210~ YTN "[생생경제] SK바사. 공모주라고 무조건 성~ "■ 방송 : YTN 라디오 FM 94.~ 2021-03-22
## 4 20210~ YTN "[생생경제] 코로나의무검사보다 근로환경개선이~ "■ 방송 : YTN 라디오 FM 94.~ 2021-03-22
## 5 20210~ 중앙일보 "\"AZ 접종 후 희귀 혈전 발생 20대 구~ "최근 아스트라제네카(AZ) 백신을 접종~ 2021-03-22
## 6 20210~ 전남일보 "이용빈, \"미얀마 군부 폭력의 희생자에 대~ "더불어민주당 이용빈(광주 광산구갑) 의~ 2021-03-22
## 7 20210~ 동아일보 "“선택적 분노 김제동 선생” 신간 리뷰 삭제~ "방송인 김제동(47)의 신간 ‘질문이 ~ 2021-03-22
## 8 20210~ 중앙일보 "김제동 책 비판 리뷰 삭제 논란 \"욕설도 ~ "방송인 김제동이 2년여 만에 신간을 출~ 2021-03-22
## 9 20210~ 중앙일보 "LH 두고 \"부동산 적폐\"→\"누적된 관~ "문재인 대통령은 22일 청와대에서 열린~ 2021-03-22
## 10 20210~ YTN "[더뉴스] [리얼미터] 문 대통령 지지율 '~ "■ 진행 : 강진원 앵커, 박상연 앵커~ 2021-03-22
## # ... with 15,880 more rows
# ymd 함수의 기능은?
cv_frames_date <- cv_frames_unique %>% mutate(date = ymd(DATE))
library(ggplot2) #시각화 예시
cv_frames_date %>%
count(date) %>%
ggplot(aes(x=date, y=n)) +
geom_col() +
scale_x_date(date_breaks = "1 month", date_labels = "%b")
cv_frames_date %>%
count(DATE) %>%
ggplot(aes(x=DATE, y=n)) +
geom_col()
RcppMeCab::pos(str_squish(cv_frames_date$HEADLINE[20:28]))
## $`전남도, 코로나 백신 안전<U+2024>신속 접종 총력`
## [1] "전남/NNP" "도/JX" ",/SC" "코로나/NNG" "백신/NNG"
## [6] "안전/NNG" "<U+2024>/SY" "신속/NNG" "접종/NNG" "총력/NNG"
##
## $`예방접종위 “AZ 백신과 혈전 연관성 없어 계속 접종해야”`
## [1] "예/IC" "방접/NNG" "종위/NNG" "“/SSO" "AZ/SL"
## [6] "백신/NNG" "과/JC" "혈전/NNG" "연관/NNG" "성/XSN"
## [11] "없/VA" "어/EC" "계속/MAG" "접종/NNG" "해야/XSV+EC"
## [16] "”/SSC"
##
## $`백신(vaccine) 이야기`
## [1] "백신/NNG" "(/SSO" "vaccine/SL" ")/SSC" "이야기/NNG"
##
## $`코로나19 백신 접종 증명서, 스마트폰으로 발급`
## [1] "코로나/NNP" "19/SN" "백신/NNG" "접종/NNG" "증명서/NNG"
## [6] ",/SC" "스마트폰/NNP" "으로/JKB" "발급/NNG"
##
## $`바디텍메드, 춘천에 65억원 투입 연구개발센터 신축 추진`
## [1] "바디/NNP" "텍/NNP" "메드/NNP" ",/SC" "춘천/NNP" "에/JKB"
## [7] "65/SN" "억/NR" "원/NNBC" "투입/NNG" "연구/NNG" "개발/NNG"
## [13] "센터/NNG" "신축/NNG" "추진/NNG"
##
## $`\u6587, 아스트라 접종 하루 전날 “백신 가짜뉴스 경계심 가져달라”`
## [1] "\u6587/NNG" ",/SC" "아스트라/NNP" "접종/NNG" "하루/NNG"
## [6] "전날/NNG" "“/SSO" "백신/NNG" "가짜/NNG" "뉴스/NNG"
## [11] "경계심/NNG" "가져/VV+EC" "달/VX" "라/EC" "”/SSC"
##
## $`대전시, 코로나19 백신 65세이상 예방접종 대상자 확정`
## [1] "대전시/NNP" ",/SC" "코로나/NNG" "19/SN" "백신/NNG"
## [6] "65/SN" "세/NNBC" "이상/NNG" "예방/NNG" "접종/NNG"
## [11] "대상자/NNG" "확정/NNG"
##
## $`요양시설 65세 이상 77% “코로나 백신 맞겠다”`
## [1] "요양/NNG" "시설/NNG" "65/SN" "세/NNBC" "이상/NNG"
## [6] "77/SN" "%/SY" "“/SSO" "코로나/NNP" "백신/NNG"
## [11] "맞/VV" "겠/EP" "다/EC" "”/SSC"
##
## $`[속보] 예방접종위 “아스트라, 혈전과 연관 없어...접종 계속해야”`
## [1] "[/SSO" "속보/NNG" "]/SSC" "예/IC" "방접/NNG"
## [6] "종위/NNG" "“/SSO" "아스트라/NNP" ",/SC" "혈전/NNG"
## [11] "과/JC" "연관/NNG" "없/VA" "어/EF" "./SF"
## [16] "../SY" "접종/NNG" "계속/NNG" "해야/XSV+EC" "”/SSC"
RcppMeCab::pos(str_remove_all(str_squish(cv_frames_date$HEADLINE[28]), "[^[:word:]#. ]"))
## $`속보 예방접종위 아스트라 혈전과 연관 없어...접종 계속해야`
## [1] "속보/NNG" "예방/NNG" "접종/NNG" "위/NNG" "아스트라/NNP"
## [6] "혈전/NNG" "과/JC" "연관/NNG" "없/VA" "어/EF"
## [11] "./SF" "../SY" "접종/NNG" "계속/NNG" "해야/XSV+EC"
select()
와 filter()
, mutate()
등 dplyr
패키지의 함수를 이용해서 데이터 처리하는 과정을 살펴봄.
tidytext
자, 이제는 “tidy” 데이터가 무엇인지, 그 원리를 살펴보고 이를 기반으로 한 어휘 빈도수 분석에 효율적인 함수를 제공하는 “tidytext” 패키지를 소개해드리도록 하겠습니다. 특히, 이 패키지의 unnest_tokens()
함수는 텍스트 전처리에 매우 편리한 기능을 제공합니다.
자 우선, tidytext
패키지와 텍스트 전처리에 필요한 stringr
패키지를 R세션에 설치해 봅시다.
library(tidytext)
library(stringr)
앞서 우리는 어휘 빈도수 분석을 위해서, 여러 전처리 과정을 거쳐왔습니다. 예를 들어, 문자열에서 구두점, 숫자, 알파벳 이외의 문자 등을 정규 표현을 이용해서 매칭하고 지워주거나 바꿔주는 전처리 작업을 했었죠. 그리고 이렇게 전처리 과정을 거친 텍스트를 단어 단위로 분석하기 위해서 빈칸을 기준으로 문자열을 쪼개는 작업을 거쳤습니다. 이를 위해 str_split()
이라는 함수를 사용했었죠.
tidytext
패키지의 unnest_tokens()
함수는 이 과정을 한번에 그리고 편리하게 수행할 수 있도록 해주는 기능을 수행합니다. apostrophe의 축약형을 제외한 텍스트의 구두점은 자동적으로 삭제하고, 알파벳을 소문자로 변환하고 빈칸을 기준으로 단어 단위로 텍스트를 쪼개서 그 결과값을 ‘tidy’ 데이터로 만들어 줍니다. 결국, 텍스트를 토큰 단위로 쪼개서 한 행에 하나의 토큰, 여기에선 한 단어씩 위치하게하는 데이터 프레임 형식으로 변환하는 기능을 수행하는 거죠.
tidy
데이터란 각 행에 하나의 토큰(여기에선 하나의 단어)만 위치하도록 구성된 테이블을 말합니다. 결국 tidy
한 데이터를 만든다는 것은 토큰의 단위를 정하고 텍스트 데이터를 토큰화하여 각 행이 하나의 토큰으로 구성되게 만든다는 것이죠. 이렇게 tidy
데이터를 구성한다는 것은 각 행이 하나의 단어씩 가지고 있기 때문에 이후 어휘 빈도수 분석 또는 사전기반 감정분석을 수행할 때 편리하게 연계 작업할 수 있다는 장점이 있습니다.
자, 다음의 R코드는 unnest_tokens()
함수를 이용해서 cv_frames_date
라는 기사 데이터를 토큰화한 과정을 보여주는데요.
cv_frames_date %>% arrange(date) # dplyr의 arrange() 함수는 해당 변수를 순차적으로 정렬 (작은 것부터); 시간의 경우 오래된 데이터부터 정렬
## # A tibble: 15,890 x 5
## DATE COMPANY HEADLINE TEXT date
## <chr> <chr> <chr> <chr> <date>
## 1 20200~ 매일신문 7조8천억 4차 추경 국회 문턱 넘었다~ "여야가 22일 7조8천억원 규모의 4차~ 2020-09-22
## 2 20200~ 매일신문 경북 안동시, '안동형 일자리 창출 모델' 본~ "경북 안동시가 중소기업과 지역특화 사업~ 2020-09-22
## 3 20200~ KBS 추경 처리 통신비 선별지원, 돌봄지원 중학생 ~ "[앵커]\r\n\r\n 7조 8천억 원~ 2020-09-22
## 4 20200~ 세계일보 文대통령 “방역 방해행위, 강력한 조치 취할 ~ "문재인 대통령. 연합뉴스 문재인 대통령~ 2020-09-22
## 5 20200~ YTN [나이트포커스] 왔다 갔다 한 '국민 통신비 ~ "■ 진행 : 오동건 앵커\r\n■ 출연~ 2020-09-22
## 6 20200~ 대전일보 코로나19 청정지역은 없다...안정세에 다시 ~ "코로나 19 예방 '사회적 거리두기' ~ 2020-09-22
## 7 20200~ 중앙일보 35~64세 통신비 빠지고 중학생도 돌봄 지원~ "‘맞춤형 재난지원금’ 지급에 쓸 4차 ~ 2020-09-22
## 8 20200~ 울산매일 여야, 4차 추경 합의 통신비 돌봄비 독감백신~ "통신비, 16 34세ㆍ65세 이상 \r~ 2020-09-22
## 9 20200~ 조선일보 7조8148억원 푼다 59년만에 4차추경안 통~ "국회는 22일 본회의를 열고 코로나 2~ 2020-09-22
## 10 20200~ 한겨레 7조8000억 규모 4차 추경 국회 본회의 통~ "여 야가 코로나19 위기 극복을 위한 ~ 2020-09-22
## # ... with 15,880 more rows
cv_frames_date %>% arrange(date) %>% unnest_tokens(word, HEADLINE, token = "words") %>% slice(1:30)
## # A tibble: 30 x 5
## DATE COMPANY TEXT date word
## <chr> <chr> <chr> <date> <chr>
## 1 202009~ 매일신문 "여야가 22일 7조8천억원 규모의 4차 추가경정예산안에 대해 통신비를 나이~ 2020-09-22 7
## 2 202009~ 매일신문 "여야가 22일 7조8천억원 규모의 4차 추가경정예산안에 대해 통신비를 나이~ 2020-09-22 조
## 3 202009~ 매일신문 "여야가 22일 7조8천억원 규모의 4차 추가경정예산안에 대해 통신비를 나이~ 2020-09-22 8
## 4 202009~ 매일신문 "여야가 22일 7조8천억원 규모의 4차 추가경정예산안에 대해 통신비를 나이~ 2020-09-22 천억
## 5 202009~ 매일신문 "여야가 22일 7조8천억원 규모의 4차 추가경정예산안에 대해 통신비를 나이~ 2020-09-22 4
## 6 202009~ 매일신문 "여야가 22일 7조8천억원 규모의 4차 추가경정예산안에 대해 통신비를 나이~ 2020-09-22 차
## 7 202009~ 매일신문 "여야가 22일 7조8천억원 규모의 4차 추가경정예산안에 대해 통신비를 나이~ 2020-09-22 추경
## 8 202009~ 매일신문 "여야가 22일 7조8천억원 규모의 4차 추가경정예산안에 대해 통신비를 나이~ 2020-09-22 국회
## 9 202009~ 매일신문 "여야가 22일 7조8천억원 규모의 4차 추가경정예산안에 대해 통신비를 나이~ 2020-09-22 문턱
## 10 202009~ 매일신문 "여야가 22일 7조8천억원 규모의 4차 추가경정예산안에 대해 통신비를 나이~ 2020-09-22 넘었다~
## # ... with 20 more rows
cv_frames_date %>% arrange(date) %>% unnest_regex(word, HEADLINE, pattern=" ") %>% slice(1:30) # dplyr의 slice() 함수는 특정 범위의 행(들)만 추출해서 보여주는 기능을 함
## # A tibble: 30 x 5
## DATE COMPANY TEXT date word
## <chr> <chr> <chr> <date> <chr>
## 1 202009~ 매일신문 "여야가 22일 7조8천억원 규모의 4차 추가경정예산안에 대해 통신비를 나~ 2020-09-22 7조8천억~
## 2 202009~ 매일신문 "여야가 22일 7조8천억원 규모의 4차 추가경정예산안에 대해 통신비를 나~ 2020-09-22 4차
## 3 202009~ 매일신문 "여야가 22일 7조8천억원 규모의 4차 추가경정예산안에 대해 통신비를 나~ 2020-09-22 추경
## 4 202009~ 매일신문 "여야가 22일 7조8천억원 규모의 4차 추가경정예산안에 대해 통신비를 나~ 2020-09-22 국회
## 5 202009~ 매일신문 "여야가 22일 7조8천억원 규모의 4차 추가경정예산안에 대해 통신비를 나~ 2020-09-22 문턱
## 6 202009~ 매일신문 "여야가 22일 7조8천억원 규모의 4차 추가경정예산안에 대해 통신비를 나~ 2020-09-22 넘었다
## 7 202009~ 매일신문 "경북 안동시가 중소기업과 지역특화 사업 중심의 '안동형 일자리 창출 모델~ 2020-09-22 경북
## 8 202009~ 매일신문 "경북 안동시가 중소기업과 지역특화 사업 중심의 '안동형 일자리 창출 모델~ 2020-09-22 안동시,~
## 9 202009~ 매일신문 "경북 안동시가 중소기업과 지역특화 사업 중심의 '안동형 일자리 창출 모델~ 2020-09-22 '안동형~
## 10 202009~ 매일신문 "경북 안동시가 중소기업과 지역특화 사업 중심의 '안동형 일자리 창출 모델~ 2020-09-22 일자리
## # ... with 20 more rows
이 코드는 cv_frames_date
는 데이터를 unnest_tokens()
함수를 이용하여, HEADLINE
라는 변수의 문자열을 단어 단위로 쪼개서 word
라는 새로운 변수에 저장해주라는 명령을 수행합니다. 여기에서 토큰화 단위는 즉, 문자열을 쪼개고자 하는 기본 단위는 token
이라는 인자를 “words”로 설정했죠. 이를 통해 단어 단위로 문자열을 토큰화하라는 설정이 취해진 것입니다.
unnest_tokens()
함수의 기능은 문자열을 단어 단위로 토큰화하라는 것 이외에 정규 표현식을 이용해서 텍스트를 토큰화하도록 할 수 있다는 점인데요. 따라서 텍스트를 쪼개는 토큰의 단위를 다양하게 설정할 수 있는 장점이 있습니다. 예를 들어서, 우리가 다루는 기사 데이터에 경우, 키워드에 단어들이 쉼표로 구분되어 있어 이를 기준으로 토큰화 방법이 필요하고, 이 때 unnest_regex()
는 유용한 기능을 합니다.
자, 이러한 tidytext
방식의 토큰화를 거치면, 뉴스 텍스트가 어휘 단위로 구분된 새로운 데이터를 얻게 되는데요. 이를 이용하면 어휘 빈도수 분석이 매우 용이합니다.
cv_tidy_count <- cv_frames_date %>%
unnest_regex(word, HEADLINE, pattern=" ") %>%
count(word, sort = TRUE)
cv_tidy_count
## # A tibble: 40,833 x 2
## word n
## <chr> <int>
## 1 백신 4182
## 2 코로나 3477
## 3 접종 1755
## 4 코로나19 664
## 5 대통령 587
## 6 문 555
## 7 첫 442
## 8 “코로나 435
## 9 美 424
## 10 화이자 394
## # ... with 40,823 more rows
cv_word_count <- cv_frames_date %>%
unnest_tokens(word, HEADLINE, token="words") %>%
count(word, sort = TRUE)
cv_word_count
## # A tibble: 27,411 x 2
## word n
## <chr> <int>
## 1 코로나 5979
## 2 백신 5428
## 3 접종 2237
## 4 19 1144
## 5 1 1015
## 6 대통령 996
## 7 명 945
## 8 3 890
## 9 2 834
## 10 美 684
## # ... with 27,401 more rows
dplyr의 count() 함수는 해당 변수 즉 벡터를 구성하는 값들의 빈도수를 계산합니다. sort 인자는 빈도수를 내림차순을 정렬할 수 있게 합니다.
단어 빈도수가 데이터 형식으로 저장된 cv_word_count의 내용을 인덱싱
cv_word_count[1:10,]
## # A tibble: 10 x 2
## word n
## <chr> <int>
## 1 코로나 5979
## 2 백신 5428
## 3 접종 2237
## 4 19 1144
## 5 1 1015
## 6 대통령 996
## 7 명 945
## 8 3 890
## 9 2 834
## 10 美 684
cv_word_count[,1:2] # 데이터 프레임 인덱싱 방법, 대괄호에 쉼표 앞에 숫자 또는 그 범위는 해당 행의 범위, 쉼표 뛰는 해당 열의 범위
## # A tibble: 27,411 x 2
## word n
## <chr> <int>
## 1 코로나 5979
## 2 백신 5428
## 3 접종 2237
## 4 19 1144
## 5 1 1015
## 6 대통령 996
## 7 명 945
## 8 3 890
## 9 2 834
## 10 美 684
## # ... with 27,401 more rows
위의 방법으로 우리는 “코로나”와 “백신”을 포함한 기사 텍스트를 단어 단위로 토큰화한 결과의 어휘 빈도수를 확인할 수 있습니다. 여기에서 가장 많이 등장하는 단어들이 대체로 그 이유가 이해가 됩니다만, 몇 단어들은 타당하지 않거나 맥락에서 벗어나 있는 경우들도 있습니다. 또한 한자 문자열이 제거되지 않은 점도 해결해야 함.
library(wordcloud)
## Loading required package: RColorBrewer
set.seed(331)
pal <- brewer.pal(8, "Dark2")
wordcloud(words = cv_word_count$word,
freq = cv_word_count$n,
min.freq = 50,
random.order =FALSE,
rot.per = 0.1,
scale = c(3, 0.5),
colors = pal)