---
title: "Sentiment analysis"
output: html_document
editor_options: 
  chunk_output_type: inline
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```

Мы на глаз обычно легко определяем является ли текст положительным, отрицательным или саркастичным. Машине это удается не так легко (или совсем не удается).  

Один из способов классификации текстов -- использование размеченных словарей. Текст воспринимается не как целое, а как набор слов, у которых есть эмоциональный окрас. 

Текст будет считаться, например, положительно окрашенным, если все или большая часть слов в нем классифицированы как положительные ("супер"|"крутой"|"замечательный" текст)

![](http://cs8.pikabu.ru/post_img/2017/04/04/0/1491256719120929511.jpg)

```{r}
library(tidytext)
library(stringr)

library(dplyr)
library(readr)
library(tibble)
library(lubridate)

library(ggplot2)
library(wordcloud)
```

###Словари  
```{r}
sentiments #в пакете tidytext
sentiments %>% count(sentiment) %>% arrange(-n)

#слово -- оценка от -5 до 5, где 5 -- позитивный сентимент, а -5 -- негативный
afinn_d <- get_sentiments("afinn")
afinn_d

#слово -- сентимент (positive/negative)
bing_d <- get_sentiments("bing")
bing_d

#слово -- сентимент (positive, negative, anger, anticipation, disgust, fear, joy, sadness, surprise, trust)
nrc_d <- get_sentiments("nrc")
nrc_d
```

Недостатки такого подхода: 
* сравнительно мало слов (27к из миллиона)  
* не учитывают контекст (хорошо vs не хорошо) -- основан на униграммах (unigrams)  
* не различают сарказм  

![](https://cs7.pikabu.ru/post_img/2017/11/22/7/151134717515030730.jpg)

###Case 1. Wine reviews 
```{r}
reviews <- read_csv("/students/aabakhitova/winemag-data_first150k.csv")[-1]
wine <- read_csv("/students/aabakhitova/winemag-data-130k-v2.csv")[-1]

reviews$description[1:2]
reviews$clean <- str_to_lower(reviews$description)

reviews$clean <- str_replace_all(reviews$clean, "[[:punct:]]", " ") %>% 
  str_replace_all("[[:digit:]]", " ") %>% 
  str_replace_all('[[:space:]]+', ' ')
reviews$clean[1:2]

reviews <- reviews %>% rownames_to_column()

tidy_reviews <- reviews %>% select(rowname, clean) %>% unnest_tokens(word, clean)

#стоп-слова
stop_words$word
tidy_reviews <- tidy_reviews %>%
  anti_join(stop_words) #минус 2 млн

#самые частотные слова
tidy_reviews %>%
  count(word) %>%
  with(wordcloud(word, n, max.words = 50))
```

Посмотрим на количество позитивных и негативных слов в текстах отзывах   
```{r}
tidy_reviews %>%
  inner_join(bing_d) %>%
  count(word, sentiment, sort = TRUE) %>%
  reshape2::acast(word ~ sentiment, value.var = "n", fill = 0) %>%
  comparison.cloud(colors = c("#F8766D", "#00BFC4"),
                   max.words = 80)
```
В чем проблема: оценочные слова, специфичные для предметной области: dark

Проверим то же самое с другим словарем: 
```{r}
tidy_reviews %>%
  inner_join(nrc_d %>% filter(sentiment == "positive"| sentiment == "negative")) %>%
  count(word, sentiment, sort = TRUE) %>%
  reshape2::acast(word ~ sentiment, value.var = "n", fill = 0) %>%
  comparison.cloud(colors = c("#F8766D", "#00BFC4"),
                   max.words = 100)

#that was the problem in the first place
reviews %>% ggplot() + geom_bar(aes(points))
```
Какая шкала? 

```{r}
wordcounts <- tidy_reviews %>%
  group_by(rowname) %>%
  summarize(words = n())

bingnegative <- get_sentiments("bing") %>% 
  filter(sentiment == "negative")

negatives <- tidy_reviews %>%
  semi_join(bingnegative) %>%
  group_by(rowname) %>%
  summarize(negativewords = n()) %>%
  left_join(wordcounts) %>%
  mutate(ratio = negativewords/words) %>%
  top_n(5) %>%
  ungroup()
negatives

reviews %>% filter(rowname %in% negatives$rowname) %>% select(description)
```
Что можно было бы посмотреть, будь у нас оценки отзывов распределены от 0 до 100?


###Case 2. Транскрипты с ted-talks
```{r}
transcripts <- read_csv("/students/aabakhitova/transcripts.csv")
ted_main <- read_csv("/students/aabakhitova/ted_main.csv")

transcripts$clean <- str_to_lower(transcripts$transcript) %>% str_replace_all("[[:punct:]]", " ") %>% str_replace_all("[[:digit:]]", " ") %>% str_replace_all('[[:space:]]+', ' ')
transcripts$clean[1]

tidy_ted <- transcripts %>% select(-transcript) %>% unnest_tokens(word, clean)
tidy_ted <- tidy_ted %>%
  anti_join(stop_words) #минус ~4 млн

tidy_ted %>%
  count(word) %>%
  top_n(5)
```

Опять же, посмотрим на самые частотные позитивные и негативные слова в транскриптах  
```{r}
tidy_ted %>%
  inner_join(get_sentiments("bing")) %>%
  count(word, sentiment, sort = TRUE) %>%
  reshape2::acast(word ~ sentiment, value.var = "n", fill = 0) %>%
  comparison.cloud(colors = c("#F8766D", "#00BFC4"),
                   max.words = 50)

wordcounts <- tidy_ted %>%
  group_by(url) %>%
  summarize(words = n())
```

Доля негативных слов в транскриптах
```{r}
negatives <- tidy_ted %>%
  semi_join(bingnegative) %>%
  group_by(url) %>%
  summarize(negativewords = n()) %>%
  left_join(wordcounts) %>%
  mutate(ratio = negativewords/words) 

top_negative  <- negatives %>%
  top_n(5) %>%
  ungroup()

negative = transcripts %>% filter(url %in% top_negative$url) %>% left_join(ted_main %>% select(title, views, url)) %>% select(-url, -clean)
#View(negative)

negatives %>% left_join(ted_main %>% select(title, views, url)) %>% ggplot() + geom_point(aes(x = ratio*100, y = views))
```

Оставим в покое долю негативных слов -- посмотрим на другие эмоции
```{r}
nrc_d %>% count(sentiment) %>% arrange(-n)
ted_sentiments <- tidy_ted %>% inner_join(nrc_d) 
ted_sentiments %>% count(sentiment) %>% arrange(-n)

surprise <- ted_sentiments %>% filter(sentiment == "surprise") %>% count(url) %>% 
  left_join(ted_sentiments %>% group_by(url) %>% summarise(total = n()) )

surprise <- surprise %>% mutate(surprise_perc = n/total * 100) %>% top_n(5, surprise_perc)

surprise <- surprise %>% 
  left_join(ted_main %>% select(title, url)) %>% select(-n, -total) %>%
  left_join(transcripts %>% select(-clean))

```

Чатики!
```{r}
load("/students/aabakhitova/shared/streaming/chat_data/ti7.rda")
ti7 <- ti7 %>% filter(channel == 2)
ti7$time <- ti7$time %>% ymd_hms()
#разделить на временные отрезки и посмотреть на слова частотные
ti7 %>% 
  ggplot() + geom_density(aes(time))

ti7 %>% 
  filter(day(time) == 2) %>% 
  ggplot() + geom_density(aes(time))

ti7 %>% 
  filter(day(time) == 2, hour(time)>17, hour(time)<19) %>% 
  ggplot() + geom_density(aes(time))
```

###Дополнительно

Подробно о tidytext: http://tidytextmining.com/sentiment.html

Небольшой словарик для русскоязычных текстов
```{r}
rus_sentiments <- read_csv("/students/aabakhitova/rus_sentiments.csv",  comment="#") 
names(rus_sentiments) <- c('word', "type_of_speech", "lemma", "sentiment", "source", "ambiguity")
```

