Автор|Ауди Априллиант Компилировать|ВКонтакте Источник | К науке о данных
Обзор
Для этого проекта мы просканировали необработанные данные 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/