59doit

감정분석 #4 감정사전 수정하기 본문

텍스트마이닝

감정분석 #4 감정사전 수정하기

yul_S2 2022. 12. 15. 11:12
반응형

# 감정 단어가 사용된 원문 살펴보기

#1  부정단어중에 긍정적인 감정으로 보이는 단어 : 모르는, 힘든

score_comment %>%
  filter(str_detect(reply, "모르는")) %>%
  select(reply)
# # A tibble: 6 x 1
# reply                                                                       
# <chr>                                                                       
# 1 "이놈은 BTS가 문통과 얼마나 가까운 사인지 모르는 놈이군"                    
# 2 "꼭 주요뉴스 떠야 사람들이 댓글 달더라. 그래서 내가 달아줄께 일단 1등 축하~ 
# 3 "나와 나의 여러분은 결국 이길 것이다. 아무도 모르는 새 아주 자연스럽게 -RM-"
# 4 "요즘가수 잘모르는데 이건 진짜 핵인정... 자랑스럽다~!!"                     
# 5 "국위선양 한건 대단 하지만 40대 이후로는 BTS 이름만 알지 히트곡은 전혀모름 ~
# 6 "방탄 군면제 안하면 불공정한 세상 인증하는거다 이름도 모르는 콩쿨에서 수상~ 
score_comment %>%
  filter(str_detect(reply, "힘든")) %>%
  select(reply)
# # A tibble: 27 x 1
# reply                                                                      
# <chr>                                                                      
# 1 코로나 19로 힘든 이 시기에 방탄소년단의 희망을 주는 노래가 있어 정말 더 힘~
# 2 대단하다 그나마 방탄이 힘든시기에 빛이되는구나                             
# 3 코로나때문에 힘든데 좋은소식들려줘서 고마워요~~♡                           
# 4 그 힘든걸 방탄소년단이 해냅니다                                            
# 5 2002년 월드컵 김대중대통령 특별귄한으로 군면제 시켜주지 않았나? BTS 빌보드~
# 6 이렇게 전국민들이 힘든시기에 역사적인 기쁨을 만들어준 bts 정말 자랑스럽 :] 
# 7 눈물나게 감격스럽네요. 이들이 어떻게 우리나라가수인지.. 대견스럽게 그지 없~
# 8 춤을 추게 하는 노래~ 힘든 시기에 큰 위로가 되었어~ HOT 100 1위까지~~ 정말 ~
# 9 이 어렵고 힘든시기에 BTS가 힘을 주고 기쁨을주는군요 너무자랑스럽고 행복하~ 
# 10 군면제 해주고, 계속 음악하게 해주세요. 빌보드 1위면 해주고도 남아야 하는거~
#  # ... with 17 more rows

 

 

#2  감정 사전 수정필요

dic %>% filter(word %in% c("힘든","모르는"))
# word polarity
# 1   힘든       -2
# 2 모르는       -1
  • 감정 사전에 부정적인 단어로 분류되어 있어서 생긴 문제
  • 텍스트의 맥락이 감정 사전의 맥락과 다르면 반대되는 감정 점수 부여

 

 

#3 감정 사전 수정하기

new_dic <- dic %>%
  mutate(polarity = ifelse(word %in% c("힘든","모르는"), 2, polarity))

new_dic %>% filter(word %in% c("힘든","모르는"))
# word polarity
# 1   힘든        2
# 2 모르는        2

힘든 의 polarity를 양수2로 수정

 

 

#4 수정한 사전으로 감정 점수 부여하기 

new_word_comment <- word_comment %>%
  select(-polarity) %>%
  left_join(new_dic, by = "word") %>%
  mutate(polarity = ifelse(is.na(polarity), 0, polarity))

 

 

#5  댓글별 감정 점수 구하기

new_score_comment <- new_word_comment %>%
  group_by(id, reply) %>%
  summarise(score = sum(polarity)) %>%
  ungroup()

new_score_comment %>%
  select(score, reply) %>%
  arrange(-score)
# # A tibble: 1,194 x 2
# score reply                                                                
#                                                                  
#   1     8 멋지다, 자랑스럽다, 대단하다 방탄소년단!!! 다이너마이트 빌보드 핫100~
#   2     7 팬은 아니야. 그래서 저 노력과 업적이 더 대단해보여. 정말 멋지다. 잘~ 
#   3     6 축하 합니다 우리에 보물이네 대한미국에 애국자 들이다 나라 홍보도하고~
#   4     6 우리딸이 보는 눈이 있네 호르몬전쟁 노래부터 애네들 좋아했는데 그때는~
#   5     6 ㅜㅜ . 진짜 이 코로나에 너희들이 빛이여. 핫백 1위라니. 모든 기록을 ~ 
#   6     6 축하 축하 아미분들도 축하^^                                          
#   7     6 정말 대단하고 자랑스럽습니다.. 국격이 업그레이드 된거 같습니다..축하~
#   8     6 빌보드 핫100 1위 축하해요 여기까지 오느라 힘들었을텐데 수고했어요 앞~
#   9     6 축하해~~ 방탄소년단~~ 빌보드 HOT 100 1위~ 듣기만 해도 배부르다~ 힘든~
#   10     6 진짜 대단하다. K팝 아시아 최고 넘어서 빌보드 1위 등극 이제 BTS가 그~ 
#   # ... with 1,184 more rows

 

 

 

#6 감정 경향 전반적으로 살펴보기 

# 6-1 감정 분류하기

new_score_comment <- new_score_comment %>%
  mutate(sentiment = ifelse(score >= 1, "pos",
                            ifelse(score <= -1, "neg", "neu")))
  • 1점 기준으로 긍정 중립 부정 분류

 

 

# 6-2 감정 범주별 빈도와 비율 구하기 

원본 감정 사전 활용

score_comment %>%
  count(sentiment) %>%
  mutate(ratio = n/sum(n)*100)

# # A tibble: 3 x 3
# sentiment     n ratio
#  <chr>     <int> <dbl>
# 1 neg         113  9.46
# 2 neu         743 62.2 
# 3 pos         338 28.3
수정한 감정 사전 활용

new_score_comment %>%
  count(sentiment) %>%
  mutate(ratio = n/sum(n)*100)

# # A tibble: 3 x 3
# sentiment     n ratio
#       
# 1 neg         102  8.54
# 2 neu         741 62.1 
# 3 pos         351 29.4

 

 

#7 분석 결과 비교

word <- "힘든|모르는"
원본 감정 사전 활용

score_comment %>%
  filter(str_detect(reply, word)) %>%
  count(sentiment)

# # A tibble: 3 x 2
# sentiment     n
#  <chr>     <int>
# 1 neg          13
# 2 neu           8
# 3 pos          12
수정한 감정 사전 활용

new_score_comment %>%
  filter(str_detect(reply, word)) %>%
  count(sentiment)

# # A tibble: 3 x 2
# sentiment     n
#  <chr>     <int>
# 1 neg           2
# 2 neu           6
# 3 pos          25
  • str_detect()에 여러 문자를 입력할 때는 |로 문자를 구분

 

#8 감정 범주별 주요 단어 보기

# 8-1 토큰화 & 전처리

new_comment <- new_score_comment %>%
  unnest_tokens(input = reply,
                output = word,
                token = "words",
                drop = F) %>%
  filter(str_detect(word, "[가-힣]") &
           str_count(word) >= 2)
  • 두 글자 이상 한글 단어만 남기고 단어 빈도 구하기

 

 

# 8-2 감정 & 단어별 빈도 구하기

new_frequency_word <- new_comment %>%
  count(sentiment, word, sort = T)

 

# 8-3 로그 오즈비 구하기

(1) wide form 으로 변환

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

 

(2) 로그 오즈비 구하기

new_comment_wide <- new_comment_wide %>%
  mutate(log_odds_ratio = log(((pos + 1) / (sum(pos + 1))) /
                                ((neg + 1) / (sum(neg + 1)))))

 

# 9 막대 그래프 만들기

# 9-1 로그 오즈비가 큰 단어기준으로

new_top10 <- new_comment_wide %>%
  group_by(sentiment = ifelse(log_odds_ratio > 0, "pos", "neg")) %>%
  slice_max(abs(log_odds_ratio), n = 10, with_ties = F)
ggplot(new_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"))




 

# 10 주요 단어가 사용된 댓글 확인

# 긍정

new_score_comment %>%
  filter(sentiment == "pos" & str_detect(reply, "자랑스럽다")) %>%
  select(reply)
# # A tibble: 77 x 1
# reply                                                                     
# <chr>                                                                     
# 1 자랑스럽다!!!!!! 축하합니다!!!!                                           
# 2 진짜.. 너무너무 자랑스럽다.. ㅠㅜ                                         
# 3 진짜 자랑스럽다!!!!!!!!!!!!!!!!                                           
# 4 고마워요 방탄 자랑스럽다!!!                                               
# 5 진짜 국위선양!! 자랑스럽다!! 아저씨가 응원한다                            
# 6 자랑스럽다 정말                                                           
# 7 멋지다, 자랑스럽다, 대단하다 방탄소년단!!! 다이너마이트 빌보드 핫100 1위 ~
# 8 자랑스럽다 역사적인 길들을 함께 걸어갈 수 있어 감사하다                   
# 9 축하 합니다 우리에 보물이네 대한미국에 애국자 들이다 나라 홍보도하고 달라~
# 10 드디어 해냈구나..고맙고 자랑스럽다 내가수~~                               
#   # ... with 67 more rows




new_score_comment %>%
  filter(sentiment == "pos" & str_detect(reply, "힘든")) %>%
  select(reply)
# # A tibble: 19 x 1
# reply                                                                      
# <chr>                                                                      
# 1 코로나 19로 힘든 이 시기에 방탄소년단의 희망을 주는 노래가 있어 정말 더 힘~
# 2 대단하다 그나마 방탄이 힘든시기에 빛이되는구나                             
# 3 이렇게 전국민들이 힘든시기에 역사적인 기쁨을 만들어준 bts 정말 자랑스럽 :] 
# 4 눈물나게 감격스럽네요. 이들이 어떻게 우리나라가수인지.. 대견스럽게 그지 없~
# 5 춤을 추게 하는 노래~ 힘든 시기에 큰 위로가 되었어~ HOT 100 1위까지~~ 정말 ~
# 6 BTS 정말 자랑스러워요 코로나때문에 힘든 요즘 화이팅되는 소식이네요 한국을 ~
# 7 이게 이게 와 진짜 핫1001위라니ㅠㅠ방탄이 역사를 쓰는구나 보이밴드가 뚫기힘~
# 8 우리나라에 이런 역사가 쓰여지다니... 정말 대단하고 이 힘든시기에 단비네요~~
# 9 축하해~~ 방탄소년단~~ 빌보드 HOT 100 1위~ 듣기만 해도 배부르다~ 힘든 시기 ~
# 10 우리의 가요가 세계에 널리, 방탄소년단의 애국이 자랑스럽습니다. 코로나로 힘~
# 11 케이팝 케이팝.... 방탄한탄 케이팝거리는거 넘..... 방탄은 그냥 케이팝이 아~ 
# 12 BTS는 올림픽 금메달보다 더 큰 일을 지금 해내고 있다.힘든 이 시국에 우리에~ 
# 13 힘든 시기에 좋은 소식 들려주고 좋은 노래로 힘나게 해줘서 고마워요 방탄 ㅠㅠ
# 14 진짜 역사적 핫백 1위~~ 다이나마이트 더 즐깁시다~~ 뮤비보구 자야지~ 방탄소~ 
# 15 빌보드 핫 100 1위 축하해!!! 진짜 힘든 길 왔는데... 더 놀라운 것은 이게 끝~ 
# 16 힘든시기에 행복한 뉴스                                                     
# 17 진짜 너무 축하합니다. 진짜 너무너무 힘든일을 방탄소년단이 드디어 해내고 말~
# 18 참 많이 힘든 올해에 벅찬 기쁨과 희망을 준 그들이 너무 자랑스럽고 고맙네요!!
# 19 넘 대단하고 자랑스럽네요 요새처럼 힘든시기에 힘나게하는 노래들려준것도 고~ 

 

# 부정

new_score_comment %>%
  filter(sentiment == "neg" & str_detect(reply, "아니다")) %>%
  select(reply)
# # A tibble: 3 x 1
# reply                                                                       
# <chr>                                                                       
# 1 의미없다. ㅎㅎ 니들이 돈버는 거 아니다.                                     
# 2 재앙이 빠져라 니가 인기 끌 목적으로 들어올 자리가 아니다. 어차피 졸개들이 ~ 
# 3 다이너마이트는 K-pop 아니다. 다이너마이트를 K-pop 이라고 생각하는 미국인은 ~

 

# 11 분석 결과 비교하기

수정한 감정 사전 결과

new_top10 %>%
  select(-pos, -neg) %>%
  arrange(-log_odds_ratio)

# # A tibble: 20 x 3
# # Groups:   sentiment [2]
# word       log_odds_ratio sentiment
# <chr>               <dbl> <chr>    
# 1 자랑스럽다           3.83 pos      
# 2 대단하다             2.87 pos      
# 3 좋은                 2.56 pos      
# 4 대단하고             2.52 pos      
# 5 대단한               2.36 pos      
# 6 사랑해               2.25 pos      
# 7 멋지다               2.18 pos      
# 8 축하                 2.18 pos      
9 힘든                 2.04 pos      
# 10 정말                 1.97 pos      
# 11 구속                -1.63 neg      
# 12 나네요              -1.63 neg      
# 13 니들이              -1.63 neg      
# 14 되어야              -1.63 neg      
# 15 들어도              -1.63 neg      
# 16 독도                -1.91 neg      
# 17 보다                -1.91 neg      
# 18 아니다              -1.91 neg      
# 19 없다                -1.91 neg      
# 20 없어서              -2.14 neg
원본 감정 사전 결과

top10 %>%
  select(-pos, -neg) %>%
  arrange(-log_odds_ratio)

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

 

 

 

 

 

 

 

 

 

반응형
Comments