Язык R для визуализации данных Twitter

машинное обучение глубокое обучение компьютерное зрение NLP

Автор|Ауди Априллиант Компилировать|ВКонтакте Источник | К науке о данных

Обзор

Для этого проекта мы просканировали необработанные данные Twitter 28-29 мая 2019 года. Кроме того, данные представлены в формате CSV (через запятую) и могут быть загружены здесь.

Привет, апрель на GitHub.com/AU…

Он включает в себя две темы: одна — это данные Джоко Видодо с ключевым словом «Джоко Видодо», а другая — данные Прабово Субианто с ключевым словом «Прабово Субианто». К ним относятся несколько переменных и информация для определения настроений пользователей. На самом деле данные содержат 16 переменных или атрибутов и более 1000 наблюдений. В таблице 1 перечислены некоторые переменные.

# 导入库
library(ggplot2)
library(lubridate)

# 加载Joko Widodo的数据
data.jokowi.df = read.csv(file = 'data-joko-widodo.csv',
                          header = TRUE,
                          sep = ',')
senti.jokowi = read.csv(file = 'sentiment-joko-widodo.csv',
                        header = TRUE,
                        sep = ',')
                        
# 加载Prabowo Subianto的数据
data.prabowo.df = read.csv(file = 'data-prabowo-subianto.csv',
                           header = TRUE,
                           sep = ',')
senti.prabowo = read.csv(file = 'sentiment-prabowo-subianto.csv',
                         header = TRUE,
                         sep = ',')

визуализация данных

Исследование данных направлено на получение любой информации из данных Twitter. Следует отметить, что данные были предварительно обработаны текстом. Мы исследуем переменные, которые считаются интересными. .

# TWEETS的条形图-JOKO WIDODO
data.jokowi.df$created = ymd_hms(data.jokowi.df$created,
                                 tz = 'Asia/Jakarta')
# 另一种制作“date”和“hour”变量的方法
data.jokowi.df$date = date(data.jokowi.df$created)
data.jokowi.df$hour = hour(data.jokowi.df$created)
# 日期2019-05-29
data.jokowi.date1 = subset(x = data.jokowi.df,
                           date == '2019-05-29')
data.hour.date1 = data.frame(table(data.jokowi.date1$hour))
colnames(data.hour.date1) = c('Hour','Total.Tweets')
# 创建数据可视化
ggplot(data.hour.date1)+
  geom_bar(aes(x = Hour,
               y = Total.Tweets,
               fill = I('blue')),
           stat = 'identity',
           alpha = 0.75,
           show.legend = FALSE)+
  geom_hline(yintercept = mean(data.hour.date1$Total.Tweets),
             col = I('black'),
             size = 1)+
  geom_text(aes(fontface = 'italic',
                label = paste('Average:',
ceiling(mean(data.hour.date1$Total.Tweets)),
                              'Tweets per hour'),
                x = 8,
                y = mean(data.hour.date1$Total.Tweets)+20),
            hjust = 'left',
            size = 4)+
  labs(title = 'Total Tweets per Hours - Joko Widodo',
       subtitle = '28 May 2019',
       caption = 'Twitter Crawling 28 - 29 May 2019')+
  xlab('Time of Day')+
  ylab('Total Tweets')+
  scale_fill_brewer(palette = 'Dark2')+
  theme_bw()
  
# TWEETS的条形图-PRABOWO SUBIANTO
data.prabowo.df$created = ymd_hms(data.prabowo.df$created,
                                  tz = 'Asia/Jakarta')
                                  
# 另一种制作“date”和“hour”变量的方法
data.prabowo.df$date = date(data.prabowo.df$created)
data.prabowo.df$hour = hour(data.prabowo.df$created)

# 日期2019-05-28
data.prabowo.date1 = subset(x = data.prabowo.df,
                            date == '2019-05-28')
data.hour.date1 = data.frame(table(data.prabowo.date1$hour))
colnames(data.hour.date1) = c('Hour','Total.Tweets')

# 日期 2019-05-29
data.prabowo.date2 = subset(x = data.prabowo.df,
                            date == '2019-05-29')
data.hour.date2 = data.frame(table(data.prabowo.date2$hour))
colnames(data.hour.date2) = c('Hour','Total.Tweets')
data.hour.date3 = rbind(data.hour.date1,data.hour.date2)
data.hour.date3$Date = c(rep(x = '2019-05-28',
                             len = nrow(data.hour.date1)),
                         rep(x = '2019-05-29',
                             len = nrow(data.hour.date2)))
data.hour.date3$Labels = c(letters,'A','B')
data.hour.date3$Hour = as.character(data.hour.date3$Hour)
data.hour.date3$Hour = as.numeric(data.hour.date3$Hour)

# 数据预处理
for (i in 1:nrow(data.hour.date3)) {
  if (i%%2 == 0) {
    data.hour.date3[i,'Hour'] = ''
  }
  if (i%%2 == 1) {
    data.hour.date3[i,'Hour'] = data.hour.date3[i,'Hour']
  }
}
data.hour.date3$Hour = as.factor(data.hour.date3$Hour)

# 数据可视化
ggplot(data.hour.date3)+
  geom_bar(aes(x = Labels,
               y = Total.Tweets,
               fill = Date),
           stat = 'identity',
           alpha = 0.75,
           show.legend = TRUE)+
  geom_hline(yintercept = mean(data.hour.date3$Total.Tweets),
             col = I('black'),
             size = 1)+
  geom_text(aes(fontface = 'italic',
                label = paste('Average:',
ceiling(mean(data.hour.date3$Total.Tweets)),
                              'Tweets per hour'),
                x = 5,
                y = mean(data.hour.date3$Total.Tweets)+6),
            hjust = 'left',
            size = 3.8)+
  scale_x_discrete(limits = data.hour.date3$Labels,
                   labels = data.hour.date3$Hour)+
  labs(title = 'Total Tweets per Hours - Prabowo Subianto',
       subtitle = '28 - 29 May 2019',
       caption = 'Twitter Crawling 28 - 29 May 2019')+
  xlab('Time of Day')+
  ylab('Total Tweets')+
  ylim(c(0,100))+
  theme_bw()+
  theme(legend.position = 'bottom',
        legend.title = element_blank())+
  scale_fill_brewer(palette = 'Dark2')

Из рисунка 1 мы можем сделать вывод, что количество твитов, полученных в результате парсинга данных (ключевые слова «Jokow Widodo» и «Prabowo Subianto»), неодинаковы даже в одну и ту же дату.

Например, на Рисунке 1 (слева) визуально твиты с ключевым словом «Джоко Видодо» были получены только в период с 03:00 до 17:00 WIB 28 мая 2019 года. А на рисунке 1 (справа) мы заключаем, что 28-29 мая 2019 г. 12:00-23:59 WIB (28 мая 2019 г.) и 00:00-15: твиты с ключевым словом «Prabowo Subianto», полученные в течение 00 WIB ( 29 мая 2019 г.).

# 2019-05-28的推特
ggplot(data.hour.date1)+
  geom_bar(aes(x = Hour,
               y = Total.Tweets,
               fill = I('red')),
           stat = 'identity',
           alpha = 0.75,
           show.legend = FALSE)+
  geom_hline(yintercept = mean(data.hour.date1$Total.Tweets),
             col = I('black'),
             size = 1)+
  geom_text(aes(fontface = 'italic',
                label = paste('Average:',
ceiling(mean(data.hour.date1$Total.Tweets)),
                              'Tweets per hour'),
                x = 6.5,
                y = mean(data.hour.date1$Total.Tweets)+5),
            hjust = 'left',
            size = 4)+
  labs(title = 'Total Tweets per Hours - Prabowo Subianto',
       subtitle = '28 May 2019',
       caption = 'Twitter Crawling 28 - 29 May 2019')+
  xlab('Time of Day')+
  ylab('Total Tweets')+
  ylim(c(0,100))+
  theme_bw()+
  scale_fill_brewer(palette = 'Dark2')
  
# 2019-05-29的推特
ggplot(data.hour.date2)+
  geom_bar(aes(x = Hour,
               y = Total.Tweets,
               fill = I('red')),
           stat = 'identity',
           alpha = 0.75,
           show.legend = FALSE)+
  geom_hline(yintercept = mean(data.hour.date2$Total.Tweets),
             col = I('black'),
             size = 1)+
  geom_text(aes(fontface = 'italic',
                label = paste('Average:',
ceiling(mean(data.hour.date2$Total.Tweets)),
                              'Tweets per hour'),
                x = 1,
                y = mean(data.hour.date2$Total.Tweets)+6),
            hjust = 'left',
            size = 4)+
  labs(title = 'Total Tweets per Hours - Prabowo Subianto',
       subtitle = '29 May 2019',
       caption = 'Twitter Crawling 28 - 29 May 2019')+
  xlab('Time of Day')+
  ylab('Total Tweets')+
  ylim(c(0,100))+
  theme_bw()+
  scale_fill_brewer(palette = 'Dark2')

Согласно рисунку 2 мы получаем существенные различия между пользователями, использующими ключевые слова «Joko Widodo» и «Prabowo Subianto». Твиты с ключевым словом «Джоко Видодо», как правило, очень интенсивно рассказывают о Джоко Видодо в определенное время (07:00–09:00 WIB), при этом наибольшее количество твитов приходится на 08:00 WIB. В нем 348 твитов. Однако в период с 28 по 29 мая 2019 г. твиты с ключевым словом «Прабово Субианто», как правило, продолжали говорить о Прабово Субианто. С 28 по 29 мая 2019 г. в час загружалось в среднем 36 твитов с ключевым словом «Prabowo Subianto».

# JOKO WIDODO
df.score.1 = subset(senti.jokowi,class == c('Negative','Positive'))
colnames(df.score.1) = c('Score','Text','Sentiment')
# Data viz
ggplot(df.score.1)+
  geom_density(aes(x = Score,
                   fill = Sentiment),
               alpha = 0.75)+
  xlim(c(-11,11))+
  labs(title = 'Density Plot of Sentiment Scores',
       subtitle = 'Joko Widodo',
       caption = 'Twitter Crawling 28 - 29 May 2019')+
  xlab('Score')+ 
  ylab('Density')+
  theme_bw()+
  scale_fill_brewer(palette = 'Dark2')+
  theme(legend.position = 'bottom',
        legend.title = element_blank())
        
# PRABOWO SUBIANTO
df.score.2 = subset(senti.prabowo,class == c('Negative','Positive'))
colnames(df.score.2) = c('Score','Text','Sentiment')
ggplot(df.score.2)+
  geom_density(aes(x = Score,
                   fill = Sentiment),
               alpha = 0.75)+
  xlim(c(-11,11))+
  labs(title = 'Density Plot of Sentiment Scores',
       subtitle = 'Prabowo Subianto',
       caption = 'Twitter Crawling 28 - 29 May 2019')+
  xlab('Density')+ 
  ylab('Score')+
  theme_bw()+
  scale_fill_brewer(palette = 'Dark2')+
  theme(legend.position = 'bottom',
        legend.title = element_blank())

На рисунке 3 представлена ​​гистограмма нескольких твитов с ключевыми словами «Joko Widodo» и «Prabowo Subianto» с 28 по 29 мая 2019 года. Из рисунка 3 (слева) можно сделать вывод, что пользователи Twitter реже говорят о Prabowo Subianto в период с 19:00 до 23:59 WIB. Это связано со временем отдыха индонезийцев. Однако эти тематические твиты всегда обновляются в полночь, потому что некоторые пользователи живут за границей, а другие все еще активны. Затем пользователь начинает активность в 04:00 WIB, достигает пика в 07:00 WIB, затем падает до 12:00 WIB, снова возрастает.

# JOKO WIDODO
df.senti.score.1 = data.frame(table(senti.jokowi$score))
colnames(df.senti.score.1) = c('Score','Freq')
# 数据预处理
df.senti.score.1$Score = as.character(df.senti.score.1$Score)
df.senti.score.1$Score = as.numeric(df.senti.score.1$Score)
Score1 = df.senti.score.1$Score
sign(df.senti.score.1[1,1])
for (i in 1:nrow(df.senti.score.1)) {
  sign.row = sign(df.senti.score.1[i,'Score'])
  for (j in 1:ncol(df.senti.score.1)) {
    df.senti.score.1[i,j] = df.senti.score.1[i,j] * sign.row
  }
}
df.senti.score.1$Label = c(letters[1:nrow(df.senti.score.1)])
df.senti.score.1$Sentiment = ifelse(df.senti.score.1$Freq < 0,
                                    'Negative','Positive')
df.senti.score.1$Score1 = Score1
# 数据可视化
ggplot(df.senti.score.1)+
  geom_bar(aes(x = Label,
               y = Freq,
               fill = Sentiment),
           stat = 'identity',
           show.legend = FALSE)+
  # 积极情感
  geom_hline(yintercept = mean(abs(df.senti.score.1[which(df.senti.score.1$Sentiment == 'Positive'),'Freq'])),
             col = I('black'),
             size = 1)+
  geom_text(aes(fontface = 'italic',
                label = paste('Average Freq:',
ceiling(mean(abs(df.senti.score.1[which(df.senti.score.1$Sentiment == 'Positive'),'Freq'])))),
                x = 10,
                y = mean(abs(df.senti.score.1[which(df.senti.score.1$Sentiment == 'Positive'),'Freq']))+30),
            hjust = 'right',
            size = 4)+
  # 消极情感
  geom_hline(yintercept = mean(df.senti.score.1[which(df.senti.score.1$Sentiment == 'Negative'),'Freq']),
             col = I('black'),
             size = 1)+
  geom_text(aes(fontface = 'italic',
                label = paste('Average Freq:',
ceiling(mean(abs(df.senti.score.1[which(df.senti.score.1$Sentiment == 'Negative'),'Freq'])))),
                x = 5,
                y = mean(df.senti.score.1[which(df.senti.score.1$Sentiment == 'Negative'),'Freq'])-15),
            hjust = 'left',
            size = 4)+
  labs(title = 'Barplot of Sentiments',
       subtitle = 'Joko Widodo',
       caption = 'Twitter Crawling 28 - 29 May 2019')+
  xlab('Score')+
  scale_x_discrete(limits = df.senti.score.1$Label,
                   labels = df.senti.score.1$Score1)+
  theme_bw()+
  scale_fill_brewer(palette = 'Dark2')

# PRABOWO SUBIANTO
df.senti.score.2 = data.frame(table(senti.prabowo$score))
colnames(df.senti.score.2) = c('Score','Freq')
# 数据预处理
df.senti.score.2$Score = as.character(df.senti.score.2$Score)
df.senti.score.2$Score = as.numeric(df.senti.score.2$Score)
Score2 = df.senti.score.2$Score
sign(df.senti.score.2[1,1])
for (i in 1:nrow(df.senti.score.2)) {
  sign.row = sign(df.senti.score.2[i,'Score'])
  for (j in 1:ncol(df.senti.score.2)) {
    df.senti.score.2[i,j] = df.senti.score.2[i,j] * sign.row
  }
}
df.senti.score.2$Label = c(letters[1:nrow(df.senti.score.2)])
df.senti.score.2$Sentiment = ifelse(df.senti.score.2$Freq < 0,
                                    'Negative','Positive')
df.senti.score.2$Score1 = Score2
# 数据可视化
ggplot(df.senti.score.2)+
  geom_bar(aes(x = Label,
               y = Freq,
               fill = Sentiment),
           stat = 'identity',
           show.legend = FALSE)+
  # 积极情感
  geom_hline(yintercept = mean(abs(df.senti.score.2[which(df.senti.score.2$Sentiment == 'Positive'),'Freq'])),
             col = I('black'),
             size = 1)+
  geom_text(aes(fontface = 'italic',
                label = paste('Average Freq:',
ceiling(mean(abs(df.senti.score.2[which(df.senti.score.2$Sentiment == 'Positive'),'Freq'])))),
                x = 11,
                y = mean(abs(df.senti.score.2[which(df.senti.score.2$Sentiment == 'Positive'),'Freq']))+20),
            hjust = 'right',
            size = 4)+
  # 消极情感
  geom_hline(yintercept = mean(df.senti.score.2[which(df.senti.score.2$Sentiment == 'Negative'),'Freq']),
             col = I('black'),
             size = 1)+
  geom_text(aes(fontface = 'italic',
                label = paste('Average Freq:',
ceiling(mean(abs(df.senti.score.2[which(df.senti.score.2$Sentiment == 'Negative'),'Freq'])))),
                x = 9,
                y = mean(df.senti.score.2[which(df.senti.score.2$Sentiment == 'Negative'),'Freq'])-10),
            hjust = 'left',
            size = 4)+
  labs(title = 'Barplot of Sentiments',
       subtitle = 'Prabowo Subianto',
       caption = 'Twitter Crawling 28 - 29 May 2019')+
  xlab('Score')+
  scale_x_discrete(limits = df.senti.score.2$Label,
                   labels = df.senti.score.2$Score1)+
  theme_bw()+
  scale_fill_brewer(palette = 'Dark2')

Рисунок 4 представляет собой карту плотности оценки тональности, содержащую ключевые слова «Joko Widodo» и «Prabowo Subianto». Оценки для твитов получаются путем усреднения оценок стеблей, из которых состоят твиты. Таким образом, его оценка дается для каждого корня со значением от -10 до 10. Чем меньше оценка, тем больше негатива в Weibo, и наоборот. Согласно рисунку 4 (слева) можно сделать вывод, что негативное отношение твитов, содержащих ключевое слово «Джоко Видодо», находится в диапазоне от -10 до -1 со средним значением -4. Это работает и на положительные эмоции (с положительным счетом, конечно). Из графика плотности на рис. 4 (слева) видно, что оценки позитивных настроений имеют довольно небольшую дисперсию. Таким образом, мы делаем вывод, что положительное отношение к Weibo, содержащему ключевое слово «Joko Widodo», не слишком разнообразно.

На рис. 4 (справа) показана карта плотности оценки тональности, содержащая ключевое слово «Prabowo Subianto». Он отличается от рисунка 4 (слева), потому что негативный тон на рисунке 4 (справа) находится между -8 и -1. Это означает, что в твитах не так много негативного настроения (твиты имеют негативное настроение, но недостаточно сильное). Кроме того, распределение оценок негативных настроений имеет два пика между 4 и 1. Однако положительные эмоции варьировались от 1 до 10. Позитивные настроения на Рисунке 4 (справа) имеют более высокую дисперсию по сравнению с Рисунком 4 (слева) с двумя пиками в диапазоне от 3 до 10. Это показывает, что Weibo, содержащий ключевое слово «Prabowo Subianto», имеет высокие положительные настроения.

# JOKO WIDODO
df.senti.3 = as.data.frame(table(senti.jokowi$class))
colnames(df.senti.3) = c('Sentiment','Freq')
# 数据预处理
df.pie.1 = df.senti.3
df.pie.1$Prop = df.pie.1$Freq/sum(df.pie.1$Freq)
df.pie.1 = df.pie.1 %>%
  arrange(desc(Sentiment)) %>%
  mutate(lab.ypos = cumsum(Prop) - 0.5*Prop)
# 数据可视化
ggplot(df.pie.1,
       aes(x = 2,
           y = Prop,
           fill = Sentiment))+
  geom_bar(stat = 'identity',
           col = 'white',
           alpha = 0.75,
           show.legend = TRUE)+
  coord_polar(theta = 'y', 
              start = 0)+
  geom_text(aes(y = lab.ypos,
                label = Prop),
            color = 'white',
            fontface = 'italic',
            size = 4)+
  labs(title = 'Piechart of Sentiments',
       subtitle = 'Joko Widodo',
       caption = 'Twitter Crawling 28 - 29 May 2019')+
  xlim(c(0.5,2.5))+
  theme_void()+
  scale_fill_brewer(palette = 'Dark2')+
  theme(legend.title = element_blank(),
        legend.position = 'right')
        
# PRABOWO SUBIANTO
df.senti.4 = as.data.frame(table(senti.prabowo$class))
colnames(df.senti.4) = c('Sentiment','Freq')
# 数据预处理
df.pie.2 = df.senti.4
df.pie.2$Prop = df.pie.2$Freq/sum(df.pie.2$Freq)
df.pie.2 = df.pie.2 %>%
  arrange(desc(Sentiment)) %>%
  mutate(lab.ypos = cumsum(Prop) - 0.5*Prop)
# 数据可视化
ggplot(df.pie.2,
       aes(x = 2,
           y = Prop,
           fill = Sentiment))+
  geom_bar(stat = 'identity',
           col = 'white',
           alpha = 0.75,
           show.legend = TRUE)+
  coord_polar(theta = 'y', 
              start = 0)+
  geom_text(aes(y = lab.ypos,
                label = Prop),
            color = 'white',
            fontface = 'italic',
            size = 4)+
  labs(title = 'Piechart of Sentiments',
       subtitle = 'Prabowo Subianto',
       caption = 'Twitter Crawling 28 - 29 May 2019')+
  xlim(c(0.5,2.5))+
  theme_void()+
  scale_fill_brewer(palette = 'Dark2')+
  theme(legend.title = element_blank(),
        legend.position = 'right')

Рисунок 5 представляет собой сводку оценок настроений твитов, которые разделены на отрицательные, нейтральные и положительные настроения. Отрицательные эмоции — это эмоции, которые оцениваются ниже нуля, нейтральные — эмоции, которые оцениваются равным нулю, а положительные эмоции — выше нуля. Как видно из рисунка 5, процент негативных настроений Weibo с ключевым словом «Joko Widodo» ниже, чем у твита с ключевым словом «Prabowo Subianto». Разница составляет 6,3%. Исследование также показало, что Weibos, содержащие ключевое слово «Joko Widodo», вызывали более высокие нейтральные и положительные эмоции, чем Weibos с ключевым словом Prabowo Subianto. Исследование, проведенное piechart, показало, что твиты с ключевым словом «Joko Widodo», как правило, вызывают более высокий процент положительных эмоций, чем твиты с ключевым словом «Prabowo Subianto». Но на карте плотности распределение положительных и отрицательных оценок тональности показывает, что микроблоги, содержащие ключевое слово «Prabowo Subianto», как правило, имеют более высокие оценки тональности по сравнению с «Joko Widodo». Он должен пройти дополнительный анализ.

На рис. 6 показаны термины или слова в твитах (ключевые слова «Joko Widodo» и «Prabowo Subianto»), которые пользователи часто загружали 28–29 мая 2019 г. С помощью этой визуализации WordCloud вы можете найти актуальные темы, которые обсуждаются по ключевым словам. Для твитов, содержащих ключевое слово «Joko Widodo», мы обнаружили, что термины «tuang», «petisi», «negara», «aman» и «nusantara» входят в первую пятерку с наибольшим количеством упоминаний каждого твита. Однако твиты, содержащие ключевое слово «Joko Widodo», обнаружили, что «Prabowo», «Subianto», «criminalisasi», «selamat» и «dubai» входят в пятерку наиболее часто встречающихся слов в каждом твите. Это косвенно показывает структуру твитов, загруженных с ключевым словом «Prabowo Subianto», то есть: почти наверняка каждый загруженный твит содержит имя «Prabowo Subianto» напрямую, а не через упоминание (@). Это связано с тем, что при предварительной обработке текста упоминание (@) было удалено.

Вы можете найти код в моем репозитории GitHub:Привет, апрель на GitHub.com/AU…

ссылка

[1] Борау К., Ульрих К., Фенг Дж., Шен Р. Микроблоги для изучения языка: использование Twitter для обучения коммуникативной и культурной компетентности (2009), Достижения в обучении через Интернет — ICWL 2009, 8-я Международная конференция, Ахен, Германия, 19–21 августа 2009 г.

Оригинальная ссылка:к data science.com/Twitter-Datang…

Добро пожаловать на сайт блога Panchuang AI:panchuang.net/

sklearn машинное обучение китайские официальные документы:sklearn123.com/

Добро пожаловать на станцию ​​сводки ресурсов блога Panchuang:docs.panchuang.net/