[R] 1. Tidy text format
반응형
1. The tidy text format
- tidy text format을 행(row)당 하나의 토큰(token)이 있는 테이블로 정의합니다.
- 토큰은 분석에서 사용하고자 하는 “단어”와 같이 의미가 있는 텍스트 단위를 의미합니다.
- 물론 토큰은 단일 단어 뿐만 아니라 n-gram, 문장 또는 단락 등이 될 수도 있습니다.
- 행당 하나의 토큰 구조를 만들기 위해서는 토큰화(tokenization)를 거쳐야 합니다.
1. 1. Contrasting tidy text with other data structures
- 문자열(String):
- 문자열, 즉 문자 벡터
- 말뭉치(Corpus):
- 이러한 유형은 일반적으로 메타데이터 및 세부정보로 주석이 달린 원시 문자열 등이 포함
- 문서-단어 행렬(Document-term matrix):
- 각 문서들이 행(row)을 이루고 문서에 포함된 단어들이 열(column)을 이루는 희소 행렬(sparse matrix)
- 행렬을 구성하는 값은 단어의 빈도 수 또는 TF-IDF가 구성됩니다.
1. 2. unnest_tokens()
function
- 아래 유명한 나태주 시인님의 시 몇가지를 예시로 들겠습니다.
text <- c("자세히 보아야 예쁘다
오래 보아야 사랑스럽다
너도 그렇다",
"꽃이 피고 새잎 나는 날
마음아 너도 거기서
꽃 피우고 새잎 내면서
놀고 있거라",
"두 셋이서 피어 있는 꽃보다
오직 혼자서 피어있는 꽃이
더 당당하고 아름다울 때 있다
너 오늘 혼자서 외롭게
꽃으로 서있음을 너무
힘들어 하지 말아라")
text
## [1] "자세히 보아야 예쁘다\n 오래 보아야 사랑스럽다\n 너도 그렇다"
## [2] "꽃이 피고 새잎 나는 날\n 마음아 너도 거기서\n 꽃 피우고 새잎 내면서\n 놀고 있거라"
## [3] "두 셋이서 피어 있는 꽃보다\n 오직 혼자서 피어있는 꽃이\n 더 당당하고 아름다울 때 있다\n 너 오늘 혼자서 외롭게\n 꽃으로 서있음을 너무\n 힘들어 하지 말아라"
- 위 텍스트 데이터는 우리가 알고있는 일반적인 문자형 벡터가 됩니다.
(\n
의미는 행바꿈을 의미하는 정규표현식 입니다.) - 이를 tidy text format으로 바꾸려면
tibble()
함수를 사용하여 프레임안에 넣을 수 있습니다.
text_df <- tibble(
seq = 1:length(text),
text = text
)
text_df
## # A tibble: 3 x 2
## seq text
## <int> <chr>
## 1 1 "자세히 보아야 예쁘다\n 오래 보아야 사랑스럽다\n 너도…
## 2 2 "꽃이 피고 새잎 나는 날\n 마음아 너도 거기서\n 꽃 피…
## 3 3 "두 셋이서 피어 있는 꽃보다\n 오직 혼자서 피어있는 꽃이\n …
- 하지만 문자열을 포함하는 이러한 데이터 프레임을 가지고 텍스트 분석을 하기에는 아직 부족합니다.
- 각 행이 여러 개의 결합된 단어나 문장 등으로 구성되어 있기 때문에 가장 자주 발생하는 단어 등을 필터링할 수 없습니다.
- 이 것을 행당 문서당 하나의 토큰(one token per document per row)을 갖도록 변환해야 합니다.
- 이 때 쓰이는 함수는
tidytext
라이브러리의unnest_tokens()
함수 입니다. unnest_tokens()
함수에 사용되는 두 가지 기본 파라미터는 아래와 같습니다.output
: unnest되어 새로 생성될 변수명input
: 텍스트가 들어있는 입력값의 변수명
text_df %>%
unnest_tokens(
input = text,
output = "word"
)
## # A tibble: 46 x 2
## seq word
## <int> <chr>
## 1 1 자세히
## 2 1 보아야
## 3 1 예쁘다
## 4 1 오래
## 5 1 보아야
## 6 1 사랑스럽다
## 7 1 너도
## 8 1 그렇다
## 9 2 꽃이
## 10 2 피고
## # … with 36 more rows
- 여기에
token
이라는 argument가 별도로 있는데 기본 값은token = "words"
입니다. - 만일 토큰을 단어 2개로 묶은 n-gram 형태로 뽑고 싶다면 아래와 같이 코드를 입력하시면 됩니다.
text_df %>%
unnest_tokens(
input = text,
output = "ngram_2",
token = "ngrams",
n = 2
)
## # A tibble: 43 x 2
## seq ngram_2
## <int> <chr>
## 1 1 자세히 보아야
## 2 1 보아야 예쁘다
## 3 1 예쁘다 오래
## 4 1 오래 보아야
## 5 1 보아야 사랑스럽다
## 6 1 사랑스럽다 너도
## 7 1 너도 그렇다
## 8 2 꽃이 피고
## 9 2 피고 새잎
## 10 2 새잎 나는
## # … with 33 more rows
1. 3. Tidying the works of Jane Austen & Word frequencies
- 메뉴얼에 소개된 방식대로 한 번 따라해보겠습니다.
janeaustenr
라이브러리에 있는 출판 소설의 텍스트 데이터를 예시로 사용하겠습니다.
library(janeaustenr)
austen_books()
## # A tibble: 73,422 x 2
## text book
## * <chr> <fct>
## 1 "SENSE AND SENSIBILITY" Sense & Sensibility
## 2 "" Sense & Sensibility
## 3 "by Jane Austen" Sense & Sensibility
## 4 "" Sense & Sensibility
## 5 "(1811)" Sense & Sensibility
## 6 "" Sense & Sensibility
## 7 "" Sense & Sensibility
## 8 "" Sense & Sensibility
## 9 "" Sense & Sensibility
## 10 "CHAPTER 1" Sense & Sensibility
## # … with 73,412 more rows
austen_books()
의 출력 결과물에 대한 설명은 아래와 같습니다.text
,book
두 개의 컬럼으로 구성되어 있는 데이터book
컬럼은 6개의 책 이름을 의미text
컬럼은 최대 약 70자 정도로 분할된 소설의 텍스트
#cumsum(): 누적합을 구하는 함수
#str_detect(): 문자열에서 특정 조건을 만족하는 문자열을 찾는 함수
#regex(): 정규표현식 관련 함수
original_books <- austen_books() %>%
group_by(book) %>%
mutate(
line_number = row_number(),
chapter = cumsum(str_detect(string = text, pattern = regex("^chapter [\\divclx]", ignore_case = TRUE)))
) %>%
ungroup()
original_books
## # A tibble: 73,422 x 4
## text book line_number chapter
## <chr> <fct> <int> <int>
## 1 "SENSE AND SENSIBILITY" Sense & Sensibility 1 0
## 2 "" Sense & Sensibility 2 0
## 3 "by Jane Austen" Sense & Sensibility 3 0
## 4 "" Sense & Sensibility 4 0
## 5 "(1811)" Sense & Sensibility 5 0
## 6 "" Sense & Sensibility 6 0
## 7 "" Sense & Sensibility 7 0
## 8 "" Sense & Sensibility 8 0
## 9 "" Sense & Sensibility 9 0
## 10 "CHAPTER 1" Sense & Sensibility 10 1
## # … with 73,412 more rows
- 이를 tidy text format으로 활용하기 위해서 똑같이
unnest_tokens()
함수를 적용하겠습니다.
tidy_books <- original_books %>%
unnest_tokens(
input = text,
output = "word"
)
tidy_books
## # A tibble: 725,055 x 4
## book line_number chapter word
## <fct> <int> <int> <chr>
## 1 Sense & Sensibility 1 0 sense
## 2 Sense & Sensibility 1 0 and
## 3 Sense & Sensibility 1 0 sensibility
## 4 Sense & Sensibility 3 0 by
## 5 Sense & Sensibility 3 0 jane
## 6 Sense & Sensibility 3 0 austen
## 7 Sense & Sensibility 5 0 1811
## 8 Sense & Sensibility 10 1 chapter
## 9 Sense & Sensibility 10 1 1
## 10 Sense & Sensibility 13 1 the
## # … with 725,045 more rows
- 텍스트 데이터를 정제하는 과정에서 종종 불필요하거나 유용하지 않는 단어는 제거할 필요가 있습니다.
- 해당 라이브러리에서는
stop_words
라는 데이터 안에 단어들이 포함되어 있습니다.
data(stop_words)
stop_words
## # A tibble: 1,149 x 2
## word lexicon
## <chr> <chr>
## 1 a SMART
## 2 a's SMART
## 3 able SMART
## 4 about SMART
## 5 above SMART
## 6 according SMART
## 7 accordingly SMART
## 8 across SMART
## 9 actually SMART
## 10 after SMART
## # … with 1,139 more rows
- 이를
anti_join()
함수를 사용하여 제거하겠습니다.tidyverse
에서anti_join()
함수의 의미는? 여기!
tidy_books <- tidy_books %>% anti_join(stop_words, by = "word")
tidy_books
## # A tibble: 217,609 x 4
## book line_number chapter word
## <fct> <int> <int> <chr>
## 1 Sense & Sensibility 1 0 sense
## 2 Sense & Sensibility 1 0 sensibility
## 3 Sense & Sensibility 3 0 jane
## 4 Sense & Sensibility 3 0 austen
## 5 Sense & Sensibility 5 0 1811
## 6 Sense & Sensibility 10 1 chapter
## 7 Sense & Sensibility 10 1 1
## 8 Sense & Sensibility 13 1 family
## 9 Sense & Sensibility 13 1 dashwood
## 10 Sense & Sensibility 13 1 settled
## # … with 217,599 more rows
- 이를 가지고
count()
함수를 사용하여 빈도가 높은 순으로 단어들을 체크해볼 수도 있습니다.
tidy_books %>%
count(word, sort = TRUE)
## # A tibble: 13,914 x 2
## word n
## <chr> <int>
## 1 miss 1855
## 2 time 1337
## 3 fanny 862
## 4 dear 822
## 5 lady 817
## 6 sir 806
## 7 day 797
## 8 emma 787
## 9 sister 727
## 10 house 699
## # … with 13,904 more rows
- 이 결과를
ggplot2
라이브러리를 활용하여 시각화해볼 수도 있습니다.
tidy_books %>%
count(word, sort = TRUE) %>%
filter(n >= 600) %>% # 빈도가 600회 이상인 단어만 추출
ggplot(aes(x = reorder(word, n), y = n)) +
geom_bar(stat = "identity", colour = "white", width = 0.8) +
coord_flip() +
labs(x = "words", y = "frequency")
반응형
'tidytext' 카테고리의 다른 글
[R] unnest_tokens() (0) | 2021.07.17 |
---|---|
[R] 2. Sentiment analysis with tidy data (0) | 2021.07.17 |
[R] 정규표현식 관련 (0) | 2021.07.15 |
[R] stringr 문자열 관련 처리 함수 (0) | 2021.07.14 |
[R] 텍스트 데이터 분석을 위한 라이브러리 준비 (0) | 2021.07.14 |
TAGS.