tidytext 패키지

요즘 R 진영에는 tidy한 작업이 대세입니다. 깔끔하게 정도로 번역을 할 수도 있지만, 최적의 단어로 번역이 어렵습니다. 쉽게 생각한다면, tidyverse 패키지군의 “tibble 구조로 데이터를 구조화하여 분석할 수 있다.” 정도의 의미 해석이 가능합니다.

이것은 한편으로는 tidyverse 패키지군과의 협업 용이성을 의미하기도 합니다. 즉, tidyverse 패키지군에서 제공하는 여러 장점을 사용할 수 있다는 것입니다. 아마도 dplyr와의 협업이 주가 될 것입니다.

다음은 CRAN에 등록된 패키지중에서 tidy라는 단어가 들어간 패키지 이름을 조사한 결과입니다. 앞으로 계속 늘어날텐데, 이 작업을 수행한 시점인 2022-07-31에는 73개 패키지가 있습니다.

library(tidyverse)

available.packages(repos = "https://cran.rstudio.com/") %>% 
  row.names() %>% 
  str_subset("tidy")
 [1] "spotidy"        "tidybayes"      "tidyBdE"        "tidybins"      
 [5] "tidyboot"       "tidycat"        "tidyCDISC"      "tidycensus"    
 [9] "tidycharts"     "tidycmprsk"     "tidycode"       "tidycomm"      
[13] "tidyCpp"        "tidycwl"        "tidydatatutor"  "tidydice"      
[17] "tidydr"         "tidyEmoji"      "tidyestimate"   "tidyfast"      
[21] "tidyfst"        "tidyft"         "tidygapminder"  "tidygate"      
[25] "tidygenomics"   "tidygeocoder"   "tidygeoRSS"     "tidygraph"     
[29] "tidyHeatmap"    "tidyhydat"      "tidyjson"       "tidylab"       
[33] "tidylda"        "tidylo"         "tidylog"        "tidyLPA"       
[37] "tidymodels"     "tidymv"         "tidync"         "tidyndr"       
[41] "tidypaleo"      "tidyplus"       "tidypmc"        "tidyposterior" 
[45] "tidypredict"    "tidyquant"      "tidyquery"      "tidyqwi"       
[49] "tidyr"          "tidyREDCap"     "tidyrgee"       "tidyRSS"       
[53] "tidyrules"      "tidyselect"     "tidySEM"        "tidyseurat"    
[57] "tidysmd"        "tidysq"         "tidystats"      "tidystopwords" 
[61] "tidystringdist" "tidysynth"      "tidytable"      "tidyterra"     
[65] "tidytext"       "tidytidbits"    "tidytransit"    "tidytreatment" 
[69] "tidytree"       "tidytuesdayR"   "tidyUSDA"       "tidyverse"     
[73] "tidyvpc"        "tidywikidatar"  "tidyxl"        

목록의 63번째 tidytext 패키지는 텍스트 데이터 분석을 수행할 때, tidyverse 패키지군의 dplyrggplot2의 기능과 더불어 쉽고 효과적인 텍스트 분석을 수행할 수 있습니다.

tidytext와의 협업

아마도 한국 텍스트분석을 수행하는 분석가중 많은 수가 tidytext 패키지를 이용할 것입니다. 그러나 영문 텍스트 분석을 수행할 목적으로 개발된 tidytext 패키지에서는 한글을 분석하는데 다소 부족한 영역이 존재합니다. 그래서 bitTA 패키지는 이 지점을 지원하여, 한글 텍스트 분석을 수행함에 있어서 tidytext 패키지를 원활히 사용할 수 있도록 도와줍니다.

한글 tokenizer

교착어인 한글은 영문과 달리, 띄어쓰기 단위인 words가 아닌 형태소 단위로 토큰화를 수행해야 텍스트 분석을 수행할 수 있습니다. 물론 경우에 따라서 words 단위의 토큰화가 유용한 경우도 있습니다.

bitTA에서는 tidytext 패키지에서 지원하지 않는, 엄밀히 말하면 tidytext 패키지 내부에서 사용하는 tokenizers 패키지에서 제공하지 않는 두개의 토크나이저(tokenizers)를 제공합니다.:

  • 형태소 토크나이저
    • morpho_mecab()
    • part-of-speech tagger 단위의 토크나이저
  • 명사 n-grams 토크나이저
    • tokenize_noun_ngrams()

tidytext 구문에서 형태소 토크나이저인 morpho_mecab()는 다음과 같이 사용합니다.

library(bitTA)
library(tidyverse)
library(tidytext)

nho_noun_indiv <- president_speech %>%
  filter(president %in% "노무현") %>%
  filter(str_detect(category, "^외교")) %>%
  tidytext::unnest_tokens(
    out = "speech_noun",
    input = "doc",
    token = morpho_mecab
  )
  
 nho_noun_indiv 

[38;5;246m# A tibble: 47,720 × 7
[39m
  id       president category  type  title                         date  speec…¹
  
[3m
[38;5;246m<chr>
[39m
[23m    
[3m
[38;5;246m<chr>
[39m
[23m     
[3m
[38;5;246m<chr>
[39m
[23m     
[3m
[38;5;246m<chr>
[39m
[23m 
[3m
[38;5;246m<chr>
[39m
[23m                         
[3m
[38;5;246m<chr>
[39m
[23m 
[3m
[38;5;246m<chr>
[39m
[23m  

[38;5;250m1
[39m DOC_0001 노무현    외교-통상 치사  
[38;5;246m"
[39m2005 한일 우정의 해 개막식 … 2005… 우정   

[38;5;250m2
[39m DOC_0001 노무현    외교-통상 치사  
[38;5;246m"
[39m2005 한일 우정의 해 개막식 … 2005… 해     

[38;5;250m3
[39m DOC_0001 노무현    외교-통상 치사  
[38;5;246m"
[39m2005 한일 우정의 해 개막식 … 2005… 개막식 

[38;5;250m4
[39m DOC_0001 노무현    외교-통상 치사  
[38;5;246m"
[39m2005 한일 우정의 해 개막식 … 2005… 축하   

[38;5;246m# … with 47,716 more rows, and abbreviated variable name ¹​speech_noun
[39m

만약 사용자 사전이 있다면 다음과 같이 user_dic 인수를 사용할 수도 있습니다.

president_speech %>%
  filter(president %in% "노무현") %>%
  filter(str_detect(category, "^외교")) %>%
  tidytext::unnest_tokens(
    out = "speech_noun",
    input = "doc",
    token = morpho_mecab,
    user_dic = user_dic
  )

명사 n-grams 토크나이저는 다음과 같이 사용합니다.

tokenize_noun_ngrams(president_speech$doc[1:2])
[[1]]
  [1] "우정 해 개막식"       "해 개막식 축하"       "개막식 축하 행사"    
  [4] "축하 행사 축하"       "행사 축하 참석"       "축하 참석 모두"      
  [7] "참석 모두 환영"       "모두 환영 감사"       "환영 감사 인사"      
 [10] "감사 인사 전"         "인사 전 이웃"         "전 이웃 옛날"        
 [13] "이웃 옛날 이웃"       "옛날 이웃 이웃"       "이웃 이웃 사정"      
 [16] "이웃 사정 통신"       "사정 통신 사절"       "통신 사절 시절"      
 [19] "사절 시절 도쿄"       "시절 도쿄 7"          "도쿄 7 연락선"       
 [22] "7 연락선 시대"        "연락선 시대 7"        "시대 7 일"           
 [25] "7 일 항공기"          "일 항공기 하루"       "항공기 하루 안"      
 [28] "하루 안 시대"         "안 시대 교통"         "시대 교통 발달"      
 [31] "교통 발달 통신"       "발달 통신 관계"       "통신 관계 경제"      
 [34] "관계 경제 교류"       "경제 교류 말"         "교류 말 긴밀"        
 [37] "말 긴밀 협력"         "긴밀 협력 국음"       "협력 국음 마음"      
 [40] "국음 마음 실행"       "마음 실행 가공"       "실행 가공 과학"      
 [43] "가공 과학 기술"       "과학 기술 옛날"       "기술 옛날 사이"      
 [46] "옛날 사이 불편"       "사이 불편 문제"       "불편 문제 생각"      
 [49] "문제 생각 상황"       "생각 상황 양국"       "상황 양국 관계"      
 [52] "양국 관계 불편"       "관계 불편 생존"       "불편 생존 자체"      
 [55] "생존 자체 위협"       "자체 위협 사이"       "위협 사이 유감"      
 [58] "사이 유감 친구"       "유감 친구 방법"       "친구 방법 관계"      
 [61] "방법 관계 숙명"       "관계 숙명 친구"       "숙명 친구 관계"      
 [64] "친구 관계 친구"       "관계 친구 친구"       "친구 친구 미래"      
 [67] "친구 미래 적극"       "미래 적극 친구"       "적극 친구 손"        
 [70] "친구 손 불행"         "손 불행 평화"         "불행 평화 번영"      
 [73] "평화 번영 미래"       "번영 미래 관계"       "미래 관계 자리"      
 [76] "관계 자리 양국"       "자리 양국 관계"       "양국 관계 도로"      
 [79] "관계 도로 표현"       "도로 표현 전"         "표현 전 경제"        
 [82] "전 경제 도로"         "경제 도로 고속도"     "도로 고속도 수준"    
 [85] "고속도 수준 정치"     "수준 정치 안보"       "정치 안보 측면"      
 [88] "안보 측면 협력"       "측면 협력 도로"       "협력 도로 활발"      
 [91] "도로 활발 개통"       "활발 개통 문화"       "개통 문화 도로"      
 [94] "문화 도로 길"         "도로 길 길"           "길 길 위"            
 [97] "길 위 장애물"         "위 장애물 양국"       "장애물 양국 협력"    
[100] "양국 협력 관계"       "협력 관계 고속도로"   "관계 고속도로 장애물"
[103] "고속도로 장애물 직시" "장애물 직시 양국"     "직시 양국 정부"      
[106] "양국 정부 국민"       "정부 국민 적극"       "국민 적극 노력"      
[109] "적극 노력 가슴"       "노력 가슴 우정"       "가슴 우정 불"        
[112] "우정 불 자리"         "불 자리 우정"         "자리 우정 불"        
[115] "우정 불 양국"         "불 양국 국민"         "양국 국민 사이"      
[118] "국민 사이 우정"       "사이 우정 따뜻"       "우정 따뜻 계기"      
[121] "따뜻 계기 이틀"       "계기 이틀 전"         "이틀 전 도쿄"        
[124] "전 도쿄 주최"         "도쿄 주최 행사"       "주최 행사 성공"      
[127] "행사 성공 성원"       "성공 성원 참석"       "성원 참석 격려"      
[130] "참석 격려 총리"       "격려 총리 국민"       "총리 국민 자리"      
[133] "국민 자리 감사"       "자리 감사 올해"       "감사 올해 양국"      
[136] "올해 양국 수교"       "양국 수교 주년"       "수교 주년 맞이"      
[139] "주년 맞이 해"         "맞이 해 일"           "해 일 양국"          
[142] "일 양국 우정"         "양국 우정 성공"       "우정 성공 때"        
[145] "성공 때 보람"         "때 보람 생각"         "보람 생각 올해"      
[148] "생각 올해 이전"       "올해 이전 활발"       "이전 활발 양국"      
[151] "활발 양국 국민"       "양국 국민 교류"       "국민 교류 국민"      
[154] "교류 국민 교류"       "국민 교류 해"         "교류 해 감사"        

[[2]]
 [1] "7 년 각하"          "년 각하 국민"       "각하 국민 신년"    
 [4] "국민 신년 인사"     "신년 인사 새해"     "인사 새해 축복"    
 [7] "새해 축복 해"       "축복 해 기원"       "해 기원 올해"      
[10] "기원 올해 양국"     "올해 양국 관계"     "양국 관계 발전"    
[13] "관계 발전 획기"     "발전 획기 전기"     "획기 전기 중"      
[16] "전기 중 교류"       "중 교류 해"         "교류 해 경제"      
[19] "해 경제 학술"       "경제 학술 문화"     "학술 문화 체육"    
[22] "문화 체육 청소년"   "체육 청소년 분야"   "청소년 분야 행사"  
[25] "분야 행사 본격"     "행사 본격 국민"     "본격 국민 교류"    
[28] "국민 교류 협력"     "교류 협력 시대"     "협력 시대 나라"    
[31] "시대 나라 교역"     "나라 교역 상대국"   "교역 상대국 투자"  
[34] "상대국 투자 대상국" "투자 대상국 한국인" "대상국 한국인 방문"
[37] "한국인 방문 서로"   "방문 서로 문화"     "서로 문화 이웃"    
[40] "문화 이웃 양국"     "이웃 양국 우호"     "양국 우호 협력"    
[43] "우호 협력 올해"     "협력 올해 교류"     "올해 교류 행사"    
[46] "교류 행사 강화"     "행사 강화 년"       "강화 년 각하"      
[49] "년 각하 합의"       "각하 합의 전면"     "합의 전면 협력"    
[52] "전면 협력 동반자"   "협력 동반자 관계"   "동반자 관계 심화"  
[55] "관계 심화 평화"     "심화 평화 공동"     "평화 공동 번영"    
[58] "공동 번영 미래"     "번영 미래 기대"     "미래 기대 각하"    
[61] "기대 각하 건강"     "각하 건강 무궁"     "건강 무궁 발전"    
[64] "무궁 발전 기원"    

# simplify = TRUE
tokenize_noun_ngrams(president_speech$doc[1], simplify = TRUE)
  [1] "우정 해 개막식"       "해 개막식 축하"       "개막식 축하 행사"    
  [4] "축하 행사 축하"       "행사 축하 참석"       "축하 참석 모두"      
  [7] "참석 모두 환영"       "모두 환영 감사"       "환영 감사 인사"      
 [10] "감사 인사 전"         "인사 전 이웃"         "전 이웃 옛날"        
 [13] "이웃 옛날 이웃"       "옛날 이웃 이웃"       "이웃 이웃 사정"      
 [16] "이웃 사정 통신"       "사정 통신 사절"       "통신 사절 시절"      
 [19] "사절 시절 도쿄"       "시절 도쿄 7"          "도쿄 7 연락선"       
 [22] "7 연락선 시대"        "연락선 시대 7"        "시대 7 일"           
 [25] "7 일 항공기"          "일 항공기 하루"       "항공기 하루 안"      
 [28] "하루 안 시대"         "안 시대 교통"         "시대 교통 발달"      
 [31] "교통 발달 통신"       "발달 통신 관계"       "통신 관계 경제"      
 [34] "관계 경제 교류"       "경제 교류 말"         "교류 말 긴밀"        
 [37] "말 긴밀 협력"         "긴밀 협력 국음"       "협력 국음 마음"      
 [40] "국음 마음 실행"       "마음 실행 가공"       "실행 가공 과학"      
 [43] "가공 과학 기술"       "과학 기술 옛날"       "기술 옛날 사이"      
 [46] "옛날 사이 불편"       "사이 불편 문제"       "불편 문제 생각"      
 [49] "문제 생각 상황"       "생각 상황 양국"       "상황 양국 관계"      
 [52] "양국 관계 불편"       "관계 불편 생존"       "불편 생존 자체"      
 [55] "생존 자체 위협"       "자체 위협 사이"       "위협 사이 유감"      
 [58] "사이 유감 친구"       "유감 친구 방법"       "친구 방법 관계"      
 [61] "방법 관계 숙명"       "관계 숙명 친구"       "숙명 친구 관계"      
 [64] "친구 관계 친구"       "관계 친구 친구"       "친구 친구 미래"      
 [67] "친구 미래 적극"       "미래 적극 친구"       "적극 친구 손"        
 [70] "친구 손 불행"         "손 불행 평화"         "불행 평화 번영"      
 [73] "평화 번영 미래"       "번영 미래 관계"       "미래 관계 자리"      
 [76] "관계 자리 양국"       "자리 양국 관계"       "양국 관계 도로"      
 [79] "관계 도로 표현"       "도로 표현 전"         "표현 전 경제"        
 [82] "전 경제 도로"         "경제 도로 고속도"     "도로 고속도 수준"    
 [85] "고속도 수준 정치"     "수준 정치 안보"       "정치 안보 측면"      
 [88] "안보 측면 협력"       "측면 협력 도로"       "협력 도로 활발"      
 [91] "도로 활발 개통"       "활발 개통 문화"       "개통 문화 도로"      
 [94] "문화 도로 길"         "도로 길 길"           "길 길 위"            
 [97] "길 위 장애물"         "위 장애물 양국"       "장애물 양국 협력"    
[100] "양국 협력 관계"       "협력 관계 고속도로"   "관계 고속도로 장애물"
[103] "고속도로 장애물 직시" "장애물 직시 양국"     "직시 양국 정부"      
[106] "양국 정부 국민"       "정부 국민 적극"       "국민 적극 노력"      
[109] "적극 노력 가슴"       "노력 가슴 우정"       "가슴 우정 불"        
[112] "우정 불 자리"         "불 자리 우정"         "자리 우정 불"        
[115] "우정 불 양국"         "불 양국 국민"         "양국 국민 사이"      
[118] "국민 사이 우정"       "사이 우정 따뜻"       "우정 따뜻 계기"      
[121] "따뜻 계기 이틀"       "계기 이틀 전"         "이틀 전 도쿄"        
[124] "전 도쿄 주최"         "도쿄 주최 행사"       "주최 행사 성공"      
[127] "행사 성공 성원"       "성공 성원 참석"       "성원 참석 격려"      
[130] "참석 격려 총리"       "격려 총리 국민"       "총리 국민 자리"      
[133] "국민 자리 감사"       "자리 감사 올해"       "감사 올해 양국"      
[136] "올해 양국 수교"       "양국 수교 주년"       "수교 주년 맞이"      
[139] "주년 맞이 해"         "맞이 해 일"           "해 일 양국"          
[142] "일 양국 우정"         "양국 우정 성공"       "우정 성공 때"        
[145] "성공 때 보람"         "때 보람 생각"         "보람 생각 올해"      
[148] "생각 올해 이전"       "올해 이전 활발"       "이전 활발 양국"      
[151] "활발 양국 국민"       "양국 국민 교류"       "국민 교류 국민"      
[154] "교류 국민 교류"       "국민 교류 해"         "교류 해 감사"        

str <- "신혼부부나 주말부부는 놀이공원 자유이용권을 즐겨 구매합니다."

tokenize_noun_ngrams(str)
[[1]]
[1] "신혼 부부 주말"     "부부 주말 부부"     "주말 부부 놀이공원"
[4] "부부 놀이공원 자유" "놀이공원 자유 이용" "자유 이용 구매"    

# 불용어 처리
tokenize_noun_ngrams(str, stopwords = "구매")
[[1]]
[1] "신혼 부부 주말"     "부부 주말 부부"     "주말 부부 놀이공원"
[4] "부부 놀이공원 자유" "놀이공원 자유 이용"
 
# 사용자 정의 사전 사용
dic_path <- system.file("dic", package = "bitTA")
dic_file <- glue::glue("{dic_path}/buzz_dic.dic")
tokenize_noun_ngrams(str, simplify = TRUE, user_dic = dic_file)
[1] "신혼부부 주말부부 놀이공원"   "주말부부 놀이공원 자유이용권"
[3] "놀이공원 자유이용권 구매"    

# n_min
tokenize_noun_ngrams(str, n_min = 1, user_dic = dic_file)
[[1]]
 [1] "신혼부부"                     "신혼부부 주말부부"           
 [3] "신혼부부 주말부부 놀이공원"   "주말부부"                    
 [5] "주말부부 놀이공원"            "주말부부 놀이공원 자유이용권"
 [7] "놀이공원"                     "놀이공원 자유이용권"         
 [9] "놀이공원 자유이용권 구매"     "자유이용권"                  
[11] "자유이용권 구매"              "구매"                        

# ngram_delim
tokenize_noun_ngrams(str, ngram_delim = ":", user_dic = dic_file)
[[1]]
[1] "신혼부부:주말부부:놀이공원"   "주말부부:놀이공원:자유이용권"
[3] "놀이공원:자유이용권:구매"    

# bi-grams
tokenize_noun_ngrams(str, n = 2, ngram_delim = ":", user_dic = dic_file)
[[1]]
[1] "신혼부부:주말부부"   "주말부부:놀이공원"   "놀이공원:자유이용권"
[4] "자유이용권:구매"    

한글 unnest_tokens

bitTA의 한글 unnest_tokens에는 명사 n-grams 토크나이즈를 지원하는 unnest_noun_ngrams() 함수가 있습니다. 이 함수는 tidytext 패키지의 unnest_tokens 함수군의 사용법과 거의 동일합니다.

tidy와 같이 회자되는 단어인 unnest“중첩을 해제한다”고 번역되지만, 이것 또한 어렵게 번역되고 있습니다.

tidy 데이터의 핵심은 데이터를 관측치인 행과 변수인 열로 구조화는 것입니다. 그리고 열에는 하나의 값인 단일 값(길이가 1인 벡터)을 포함해야 합니다. 즉, 행의 차원와 열의 차원으로 구성된 2차원 데이터 구조가 tidy 데이터입니다.

그런데 하나의 관측치에서 특정 변수의 값이 단일 값이 아닌 경우가 있습니다. 마치 R의 리스트처럼 여러 값으로 구성되어 있습니다. 이 경우에서 문제가 되는 특정 열의 여러 정보를 풀어서 단일 정보로 변환하는 것이 unnest입니다. 결국의 해당 변수의 단일 정보 개수만큼 관측치(행)를 복제한 후, 해당 열에 각각의 단일 정보만 넣는 작업이 unnest입니다.

다음의 한용운님의 님의 침묵 시에서 첫번째와 두번째 줄을 tibble 객체로 만든 것입니다.

docs <- c("님은 갔습니다. 아아, 사랑하는 나의 님은 갔습니다.",
          "푸른 산빛을 깨치고 단풍나무 숲을 향하여 난 작은 길을 걸어서, 차마 떨치고 갔습니다.")

poem <- tibble(
= rep(1, 2),
= 1:2,
  내용 = docs
)

poem

[38;5;246m# A tibble: 2 × 3
[39m
     연    행 내용                                                              
  
[3m
[38;5;246m<dbl>
[39m
[23m 
[3m
[38;5;246m<int>
[39m
[23m 
[3m
[38;5;246m<chr>
[39m
[23m                                                             

[38;5;250m1
[39m     1     1 님은 갔습니다. 아아, 사랑하는 나의 님은 갔습니다.                 

[38;5;250m2
[39m     1     2 푸른 산빛을 깨치고 단풍나무 숲을 향하여 난 작은 길을 걸어서, 차마…

우리는 시의 내용에서 다음처럼 일반명사만 추출했습니다. 명사를 추출한 변수 명사에는 첫 행에는 3개의 명사(정보)가, 둘째 행에는 5개의 명사(정보)가 들어있습니다.

poem %>% 
  mutate(명사 = collapse_noun(내용)) %>% 
  select(-내용)

[38;5;246m# A tibble: 2 × 3
[39m
     연    행 명사                
  
[3m
[38;5;246m<dbl>
[39m
[23m 
[3m
[38;5;246m<int>
[39m
[23m 
[3m
[38;5;246m<chr>
[39m
[23m               

[38;5;250m1
[39m     1     1 님 사랑 님          

[38;5;250m2
[39m     1     2 산 빛 단풍나무 숲 길

그런데 텍스트 분석에서는 문장 레벨의 분석보다는 토큰(한글 텍스트 데이터에서는 명사) 레벨로 분석합니다. 이것은 개별 행에서의 분석의 대상이 되는 컬럼에는 단일 토큰을 넣어야 한다는 의미입니다. 즉 개별 토큰 레벨의 unnest 작업이 필요합니다.

한글 텍스트 데이터에서 일반명사를 추출한 후 이것을 tidy한 데이터로 만들기 위해서는 tidytextunnest_tokens() 함수에 토크나이저로 bitTAmorpho_mecab()를 사용합니다. 원하는 모습의 tidy 데이터가 만들어진 것입니닫.

poem %>% 
  unnest_tokens(
    명사,
    내용,
    token = morpho_mecab
  )

[38;5;246m# A tibble: 8 × 3
[39m
     연    행 명사 
  
[3m
[38;5;246m<dbl>
[39m
[23m 
[3m
[38;5;246m<int>
[39m
[23m 
[3m
[38;5;246m<chr>
[39m
[23m

[38;5;250m1
[39m     1     1

[38;5;250m2
[39m     1     1 사랑 

[38;5;250m3
[39m     1     1

[38;5;250m4
[39m     1     2

[38;5;246m# … with 4 more rows
[39m

unnest 작업은 다음처럼 얻는 것과 잃는 것이 있습니다.

  • 얻는 것
    • tidy한 데이터 구조로 변환하였기 때문에 연산이 쉽고, 이해하기 쉽다.
  • 잃는 것
    • 불필요한 데이터가 반복적으로 복제되어 데이터의 크기가 늘어난다.

unnest_noun_ngrams()

bitTAunnest_noun_ngrams()는 추출된 n-grams 명사 토큰들을 tibble의 컬럼에 하나씩 붙여줍니다.

다음은 대통령 연설문의 명사 bi-grams를 추출하여, noun_bigram 변수에 개별 토큰을 넣습니다.

president_speech %>%
  select(title, doc) %>% 
  filter(row_number() <= 2) %>%
  unnest_noun_ngrams(
    noun_bigram,
    doc,
    n = 2,
    ngram_delim = ":",
    type = "noun2"
  )

[38;5;246m# A tibble: 271 × 2
[39m
  title                              noun_bigram
  
[3m
[38;5;246m<chr>
[39m
[23m                              
[3m
[38;5;246m<chr>
[39m
[23m      

[38;5;250m1
[39m 
[38;5;246m"
[39m2005 한일 우정의 해 개막식 축사 
[38;5;246m"
[39m 일:우정    

[38;5;250m2
[39m 
[38;5;246m"
[39m2005 한일 우정의 해 개막식 축사 
[38;5;246m"
[39m 우정:

[38;5;250m3
[39m 
[38;5;246m"
[39m2005 한일 우정의 해 개막식 축사 
[38;5;246m"
[39m 해:개막식  

[38;5;250m4
[39m 
[38;5;246m"
[39m2005 한일 우정의 해 개막식 축사 
[38;5;246m"
[39m 개막식:축하

[38;5;246m# … with 267 more rows
[39m

noun_bigram 변수에, ngram_delim = ":"로 토큰의 개별 단어들을 묶어주는 문자에 기본값인 공백이 아닌 콜론(:)을 지정합니다. 그리고 drop = FALSE는 토큰화하려는 변수인 doc를 보존합니다.

president_speech %>%
  select(title, doc) %>% 
  filter(row_number() <= 2) %>%
  unnest_noun_ngrams(
    noun_bigram,
    doc,
    n = 2,
    ngram_delim = ":",
    drop = FALSE
  )   

[38;5;246m# A tibble: 222 × 3
[39m
  title                              doc                                noun_b…¹
  
[3m
[38;5;246m<chr>
[39m
[23m                              
[3m
[38;5;246m<chr>
[39m
[23m                              
[3m
[38;5;246m<chr>
[39m
[23m   

[38;5;250m1
[39m 
[38;5;246m"
[39m2005 한일 우정의 해 개막식 축사 
[38;5;246m"
[39m 
[38;5;246m"
[39m  먼저 한,일 우정의 해 개막식을 … 우정:해 

[38;5;250m2
[39m 
[38;5;246m"
[39m2005 한일 우정의 해 개막식 축사 
[38;5;246m"
[39m 
[38;5;246m"
[39m  먼저 한,일 우정의 해 개막식을 … 해:개막…

[38;5;250m3
[39m 
[38;5;246m"
[39m2005 한일 우정의 해 개막식 축사 
[38;5;246m"
[39m 
[38;5;246m"
[39m  먼저 한,일 우정의 해 개막식을 … 개막식:…

[38;5;250m4
[39m 
[38;5;246m"
[39m2005 한일 우정의 해 개막식 축사 
[38;5;246m"
[39m 
[38;5;246m"
[39m  먼저 한,일 우정의 해 개막식을 … 축하:행…

[38;5;246m# … with 218 more rows, and abbreviated variable name ¹​noun_bigram
[39m

unnest_noun_ngrams() 함수는 group_by() 함수 함께 사용할 수 있습니다.

# grouping using group_by() function
president_speech %>%
  filter(row_number() <= 4) %>%
  mutate(speech_year = substr(date, 1, 4)) %>% 
  select(speech_year, title, doc) %>% 
  group_by(speech_year) %>%
  unnest_noun_ngrams(
    noun_bigram,
    doc,
    n = 2,
    ngram_delim = ":"
  )

[38;5;246m# A tibble: 1,806 × 2
[39m

[38;5;246m# Groups:   speech_year [2]
[39m
  speech_year noun_bigram
  
[3m
[38;5;246m<chr>
[39m
[23m       
[3m
[38;5;246m<chr>
[39m
[23m      

[38;5;250m1
[39m 2005        우정:

[38;5;250m2
[39m 2005:개막식  

[38;5;250m3
[39m 2005        개막식:축하

[38;5;250m4
[39m 2005        축하:행사  

[38;5;246m# … with 1,802 more rows
[39m

group_by() 함수를 사용하지 않고도 동일한 작업을 수행할 수 있습니다. collapse 인수를 사용하면 됩니다.

# grouping using collapse argument
president_speech %>%
  filter(row_number() <= 4) %>%
  mutate(speech_year = substr(date, 1, 4)) %>% 
  select(speech_year, title, doc) %>% 
  unnest_noun_ngrams(
    noun_bigram,
    doc,
    n = 2,
    ngram_delim = ":",
    collapse = "speech_year"
  )

[38;5;246m# A tibble: 1,806 × 2
[39m
  speech_year noun_bigram
  
[3m
[38;5;246m<chr>
[39m
[23m       
[3m
[38;5;246m<chr>
[39m
[23m      

[38;5;250m1
[39m 2005        우정:

[38;5;250m2
[39m 2005:개막식  

[38;5;250m3
[39m 2005        개막식:축하

[38;5;250m4
[39m 2005        축하:행사  

[38;5;246m# … with 1,802 more rows
[39m

unnest_noun_ngrams()는 … 인수를 지원해서 tokenize_noun_ngrams()에서 사용할 수 있는 인수도 사용가능합니다. 즉, 사용자 정의 사전으로 명사를 추출할 수도 있습니다. 그리고 이런 일련의 작업들이 병렬로 처리됩니다.

args(unnest_noun_ngrams)
function (tbl, output, input, n = 3L, n_min = n, ngram_delim = " ", 
    drop = TRUE, collapse = NULL, ...) 
NULL

향후 일정

앞으로도 bitTA 패키지는 tidytext와의 협업을 모토로, tidytext에서 사용할 수 있는 유용한 기능을 추가해 나갈 것입니다.