Анализ настроений (AFINN) в R
Я пытаюсь настроить набор данных твитов, используя словарь AFINN (get_sentiments("afinn"). Пример набора данных представлен ниже:
A tibble: 10 x 2
Date TweetText
<dttm> <chr>
1 2018-02-10 21:58:19 "RT @RealSirTomJones: Still got the moves! That was a lo~
2 2018-02-10 21:58:19 "Yass Tom \U0001f600 #snakehips still got it #TheVoiceUK"
3 2018-02-10 21:58:19 Yasss tom he’s some chanter #TheVoiceUK #ItsNotUnusual
4 2018-02-10 21:58:20 #TheVoiceUK SIR TOM JONES...HE'S STILL HOT... AMAZING VO~
5 2018-02-10 21:58:21 I wonder how many hips Tom Jones has been through? #TheV~
6 2018-02-10 21:58:21 Tom Jones has still got it!!! #TheVoiceUK
7 2018-02-10 21:58:21 Good grief Tom Jones is amazing #TheVoiceuk
8 2018-02-10 21:58:21 RT @tonysheps: Sir Thomas Jones you’re a bloody legend #~
9 2018-02-10 21:58:22 @ITV Tom Jones what a legend!!! ❤️ #StillGotIt #TheVoice~
10 2018-02-10 21:58:22 "RT @RealSirTomJones: Still got the moves! That was a lo~
Что я хочу сделать: 1. Разделить твиты на отдельные слова. 2. Оцените эти слова, используя лексикон AFINN. 3. Суммируйте оценку всех слов каждого твита. 4. Верните эту сумму в новый третий столбец, чтобы я мог видеть оценку по твиту.
Для подобной лексики я нашел следующий код:
# Initiate the scoreTopic
scoreTopic <- 0
# Start a loop over the documents
for (i in 1:length (myCorpus)) {
# Store separate words in character vector
terms <- unlist(strsplit(myCorpus[[i]]$content, " "))
# Determine the number of positive matches
pos_matches <- sum(terms %in% positive_words)
# Determine the number of negative matches
neg_matches <- sum(terms %in% negative_words)
# Store the difference in the results vector
scoreTopic [i] <- pos_matches - neg_matches
} # End of the for loop
dsMyTweets$score <- scoreTopic
Однако я не могу настроить этот код, чтобы он работал со словарем afinn.
2 ответа
Это было бы отличным примером использования принципов аккуратных данных. Давайте настроим некоторые примеры данных (это мои настоящие твиты).
library(tidytext)
library(tidyverse)
tweets <- tribble(
~tweetID, ~TweetText,
1, "Was Julie helping me because I don't know anything about Python package management? Yes, yes, she was.",
2, "@darinself OMG, this is my favorite.",
3, "@treycausey @ftrain THIS IS AMAZING.",
4, "@nest No, no, not in error. Just the turkey!",
5, "The @nest people should write a blog post about how many smoke alarms went off yesterday. (I know ours did.)")
Теперь у нас есть пример данных. В приведенном ниже коде unnest_tokens()
токенизирует текст, то есть разбивает его на отдельные слова (пакет tidytext позволяет использовать специальный токенизатор для твитов) и inner_join()
реализует анализ настроений.
tweet_sentiment <- tweets %>%
unnest_tokens(word, TweetText, token = "tweets") %>%
inner_join(get_sentiments("afinn"))
#> Joining, by = "word"
Теперь мы можем найти оценки для каждого твита. Возьмите оригинальный набор данных твитов и left_join()
на это sum()
баллов за каждый твит. Удобная функция replace_na()
из тидыр позволяет заменить полученный NA
значения с нуля.
tweets %>%
left_join(tweet_sentiment %>%
group_by(tweetID) %>%
summarise(score = sum(score))) %>%
replace_na(list(score = 0))
#> Joining, by = "tweetID"
#> # A tibble: 5 x 3
#> tweetID TweetText score
#> <dbl> <chr> <dbl>
#> 1 1. Was Julie helping me because I don't know anything about … 4.
#> 2 2. @darinself OMG, this is my favorite. 2.
#> 3 3. @treycausey @ftrain THIS IS AMAZING. 4.
#> 4 4. @nest No, no, not in error. Just the turkey! -4.
#> 5 5. The @nest people should write a blog post about how many … 0.
Создано 2018-05-09 пакетом представлением (v0.2.0).
Если вы интересуетесь анализом настроений и анализом текста, я приглашаю вас ознакомиться с обширной документацией и учебными пособиями, которые есть у нас для tidytext.
Для дальнейшего использования:
Score_word <- function(x) {
word_bool_vec <- get_sentiments("afinn")$word==x
score <- get_sentiments("afinn")$score[word_bool_vec]
return (score) }
Score_tweet <- function(sentence) {
words <- unlist(strsplit(sentence, " "))
words <- as.vector(words)
scores <- sapply(words, Score_word)
scores <- unlist(scores)
Score_tweet <- sum(scores)
return (Score_tweet)
}
dsMyTweets$score<-apply(df, 1, Score_tweet)
Это выполняет то, что я изначально хотел!:)