텍스트마이닝

감정분석 #3 감정 범주별 빈도 구하기

yul_S2 2022. 12. 15. 09:53
반응형

# 감정 범주별 단어 빈도 구하기

#1  토큰화 하고 두글자 이상 한글 단어만 남기기

comment <- score_comment %>%
  unnest_tokens(input = reply, 
                output = word,
                token = "words",
                drop = F) %>%
  filter(str_detect(word, "[가-힣]") & 
           str_count(word) >= 2)
  • input = reply : 단어 기준 토큰화
  • str_detect(word, "[가-힣]") : 한글 추출
  • str_count(word) >= 2) : 두 글자 이상 추출

 

 

#2 감정 및 단어별 빈도 구하기

frequency_word <- comment %>%
  filter(str_count(word) >= 2) %>%
  count(sentiment, word, sort = T)

frequency_word
# # A tibble: 6,318 x 3
#  sentiment word           n
#  <chr>     <chr>      <int>
# 1 pos       진짜          90
# 2 neu       진짜          79
# 3 pos       자랑스럽다    77
# 4 pos       너무          70
# 5 neu       빌보드        66
# 6 pos       정말          57
# 7 neu       군면제        48
# 8 neu       방탄소년단    48
# 9 neu       축하해요      45
# 10 neu       정말          42
# # ... with 6,308 more rows

 

긍정댓글 고빈도

frequency_word %>% filter(sentiment=="pos")

# sentiment word           n
# <chr>     <chr>      <int>
# 1 pos       진짜          90
# 2 pos       자랑스럽다    77
# 3 pos       너무          70
# 4 pos       정말          57
# 5 pos       빌보드        40
# 6 pos       방탄          39
# 7 pos       방탄소년단    39
# 8 pos       축하해        36
# 9 pos       대단하다      29
# 10 pos       좋은          21
# # ... with 2,163 more rows

부정댓글 고빈도

frequency_word %>% filter(sentiment=="neg")
# # A tibble: 1,091 x 3
# sentiment word           n
# <chr>     <chr>      <int>
# 1 neg       진짜          20
# 2 neg       빌보드        15
# 3 neg       너무          14
# 4 neg       방탄소년단    13
# 5 neg       축하해        11
# 6 neg       방탄           8
# 7 neg       축하해요       8
# 8 neg       핫백           7
# 9 neg       힘든           7
# 10 neg       군면제         6
# # ... with 1,081 more rows

 

 

#2-1 상대적으로 자주 사용된 단어 비교하기

(1) 오즈비 구하기

comment_wide <- frequency_word %>%
  filter(sentiment != "neu") %>%
  pivot_wider(names_from = sentiment,
              values_from = n,
              values_fill = list(n = 0))

comment_wide             # wide form 으로 변환
# # A tibble: 3,009 x 3
# word         pos   neg
# <chr>      <int> <int>
#   1 진짜          90    20
# 2 자랑스럽다    77     0
# 3 너무          70    14
# 4 정말          57     5
# 5 빌보드        40    15
# 6 방탄          39     8
# 7 방탄소년단    39    13
# 8 축하해        36    11
# 9 대단하다      29     0
# 10 좋은          21     0
# # ... with 2,999 more rows

 

(2) 로그 오즈비 구하기

comment_wide <- comment_wide %>%
  mutate(log_odds_ratio = log(((pos + 1) / (sum(pos + 1))) /
                                ((neg + 1) / (sum(neg + 1)))))
comment_wide
# # A tibble: 3,009 x 4
#  word         pos   neg log_odds_ratio
#  <chr>       <int> <int>          <dbl>
# 1 진짜          90    20          1.05 
# 2 자랑스럽다    77     0          3.94 
# 3 너무          70    14          1.14 
# 4 정말          57     5          1.85 
# 5 빌보드        40    15          0.526
# 6 방탄          39     8          1.08 
# 7 방탄소년단    39    13          0.635
# 8 축하해        36    11          0.711
# 9 대단하다      29     0          2.99 
# 10 좋은          21     0          2.68 
# # ... with 2,999 more rows

 

 

(3) 로그 오즈비가 가장 큰 단어 10개씩 추출하기

top10 <- comment_wide %>%
  group_by(sentiment = ifelse(log_odds_ratio > 0, "pos", "neg")) %>%
  slice_max(abs(log_odds_ratio), n = 10, with_ties = F)

top10
# # A tibble: 20 x 5
# # Groups:   sentiment [2]
#  word         pos   neg log_odds_ratio sentiment
#  <chr>       <int> <int>          <dbl> <chr>    
# 1 국내           0     5          -2.21 neg      
# 2 모르는         0     4          -2.02 neg      
# 3 없어서         0     4          -2.02 neg      
# 4 있다           0     4          -2.02 neg      
# 5 널리           0     3          -1.80 neg      
# 6 독도           0     3          -1.80 neg      
# 7 보다           0     3          -1.80 neg      
# 8 아니다         0     3          -1.80 neg      
# 9 없다           0     3          -1.80 neg      
# 10 케이팝         0     3          -1.80 neg      
# 11 자랑스럽다    77     0           3.94 pos      
# 12 대단하다      29     0           2.99 pos      
# 13 좋은          21     0           2.68 pos      
# 14 대단하고      20     0           2.63 pos      
# 15 대단한        17     0           2.48 pos      
# 16 사랑해        15     0           2.36 pos      
# 17 멋지다        14     0           2.29 pos      
# 18 축하          14     0           2.29 pos      
# 19 열심히        10     0           1.98 pos      
# 20 인정          10     0           1.98 pos  

 

 

 

#3 막대그래프 만들기

ggplot(top10, aes(x = reorder(word, log_odds_ratio),
                 y = log_odds_ratio,
                 fill = sentiment)) +
  geom_col() +
  coord_flip() +
  labs(x = NULL) +
  theme(text = element_text(family = "nanumgothic"))




 

 

반응형