导言

通常不会发布关于政治的信息(我对投票不是特别精明,这是数据科学对政治产生最大影响的地方),但本周末我看到了一个关于唐纳德特朗普的推特账户的假设,这个假设只是被要求调查有数据:

当特朗普祝奥运队好运时,他正在用他的iPhone发推文。当他侮辱竞争对手时,他通常会从Android上发推文。这是一个工件,显示哪些推文是特朗普自己的,哪些是由一些处理程序?

其他人已经探索了特朗普的时间表,并注意到这种情况往往会持续下去 - 特朗普本人确实从三星Galaxy发了推文。但是,我们怎么能定量地检查呢?我最近一直在撰写关于文本挖掘和情感分析的文章,特别是在我与Julia Silge开发tidytext R软件包期间,这是一个很好的机会再次应用它。

我的分析如下所示,结论是Android和iPhone的推文显然来自不同的人,在一天的不同时间发布,并以不同的方式使用主题标签,链接和转发。更重要的是,我们可以看到Android推文更加愤怒,更负面,而iPhone的推文往往是良性的公告和图片。总的来说,我同意tvaziri的分析:这让我们可以分辨出广告系列的推文(iPhone)和特朗普自己的推特(Android)。

数据集

首先,我们将使用twitteR包中的userTimeline函数检索Donald Trump时间轴的内容:

library(dplyr)library(purrr)library(twitteR)
# You'd need to set global options with an authenticated appsetup_twitter_oauth(getOption("twitter_consumer_key"),                    getOption("twitter_consumer_secret"),                    getOption("twitter_access_token"),                    getOption("twitter_access_token_secret"))# We can request only 3200 tweets at a time; it will return fewer# depending on the APItrump_tweets <- userTimeline("realDonaldTrump", n = 3200)trump_tweets_df <- tbl_df(map_df(trump_tweets, as.data.frame))
# if you want to follow along without setting up Twitter authentication,# just use my dataset:load(url("http://varianceexplained.org/files/trump_tweets_df.rda"))# if you want to follow along without setting up Twitter authentication,# just use my dataset:load(url("http://varianceexplained.org/files/trump_tweets_df.rda"))

我们稍微清理这些数据,解压缩源应用程序。(我们只关注iPhone和Android推文)

library(tidyr)tweets <- trump_tweets_df %>%  select(id, statusSource, text, created) %>%  extract(statusSource, "source", "Twitter for (.*?)<") %>%  filter(source %in% c("iPhone", "Android"))tweets <- trump_tweets_df %>%  select(id, statusSource, text, created) %>%  extract(statusSource, "source", "Twitter for (.*?)<") %>%  filter(source %in% c("iPhone", "Android"))

总而言之,这包括来自iPhone的628条推文和来自Android的762条推文。考虑到推文的时间,我们希望它们是用户的“签名”。这里我们发现了一个区别:

library(lubridate)library(scales)tweets %>%  count(source, hour = hour(with_tz(created, "EST"))) %>%  mutate(percent = n / sum(n)) %>%  ggplot(aes(hour, percent, color = source)) +  geom_line() +  scale_y_continuous(labels = percent_format()) +  labs(x = "Hour of day (EST)",       y = "% of tweets",       color = "")library(scales)tweets %>%  count(source, hour = hour(with_tz(created, "EST"))) %>%  mutate(percent = n / sum(n)) %>%  ggplot(aes(hour, percent, color = source)) +  geom_line() +  scale_y_continuous(labels = percent_format()) +  labs(x = "Hour of day (EST)",       y = "% of tweets",       color = "")

Android上特朗普在早上发布了更多的推文,而下午和傍晚的宣传活动更多的来自iPhone。

另一个我们发现的差异是特朗普通过复制粘贴他们的推文来“手动转发”人的不合时宜的行为,然后用引号引起来:

所有这些推文几乎都是从Android发布的:

在本文剩余的文本分析中,我将过滤掉这些引用的推文(因为它们包含来自其他人的文本,可能无法代表特朗普自己的推文)。

在其他地方我们可以看到差异涉及在推文中共享链接或图片。

tweet_picture_counts <- tweets %>%  filter(!str_detect(text, '^"')) %>%  count(source,        picture = ifelse(str_detect(text, "t.co"),                         "Picture/link", "No picture/link"))ggplot(tweet_picture_counts, aes(source, n, fill = picture)) +  geom_bar(stat = "identity", position = "dodge") +  labs(x = "", y = "Number of tweets", fill = "")'^"')) %>%  count(source,        picture = ifelse(str_detect(text, "t.co"),                         "Picture/link", "No picture/link"))ggplot(tweet_picture_counts, aes(source, n, fill = picture)) +  geom_bar(stat = "identity", position = "dodge") +  labs(x = "", y = "Number of tweets", fill = "")

事实证明,iPhone的推文包含图片或链接的可能性是Android的38倍。这也与我们的叙述有关:iPhone倾向于写关于事件的“公告”推文,如下所示:

特朗普的Android推文更倾向于编写无图片的内容,如:

词语比较

现在,我们相信有这两个账户之间的差异,但是,内容上存在着怎样的差异呢?我们将使用Julia Silge 和我开发的tidytext 包。

我们首先使用 unnest_tokens 函数划分单个单词:

library(tidytext)reg <- "([^A-Za-z\d#@']|'(?![A-Za-z\d#@]))"tweet_words <- tweets %>%  filter(!str_detect(text, '^"')) %>%  mutate(text = str_replace_all(text, "https://t.co/[A-Za-z\d]+|&", "")) %>%  unnest_tokens(word, text, token = "regex", pattern = reg) %>%  filter(!word %in% stop_words$word,         str_detect(word, "[a-z]"))tweet_words  ## # A tibble: 8,753 x 4##                    id source             created                   word##                 <chr>  <chr>              <time>                  <chr>## 1  676494179216805888 iPhone 2015-12-14 20:09:15                 record## 2  676494179216805888 iPhone 2015-12-14 20:09:15                 health## 3  676494179216805888 iPhone 2015-12-14 20:09:15 #makeamericagreatagain## 4  676494179216805888 iPhone 2015-12-14 20:09:15             #trump2016## 5  676509769562251264 iPhone 2015-12-14 21:11:12               accolade## 6  676509769562251264 iPhone 2015-12-14 21:11:12             @trumpgolf## 7  676509769562251264 iPhone 2015-12-14 21:11:12                 highly## 8  676509769562251264 iPhone 2015-12-14 21:11:12              respected## 9  676509769562251264 iPhone 2015-12-14 21:11:12                   golf## 10 676509769562251264 iPhone 2015-12-14 21:11:12                odyssey## # ... with 8,743 more rows##                    id source             created                   word##                 <chr>  <chr>              <time>                  <chr>## 1  676494179216805888 iPhone 2015-12-14 20:09:15                 record## 2  676494179216805888 iPhone 2015-12-14 20:09:15                 health## 3  676494179216805888 iPhone 2015-12-14 20:09:15 #makeamericagreatagain## 4  676494179216805888 iPhone 2015-12-14 20:09:15             #trump2016## 5  676509769562251264 iPhone 2015-12-14 21:11:12               accolade## 6  676509769562251264 iPhone 2015-12-14 21:11:12             @trumpgolf## 7  676509769562251264 iPhone 2015-12-14 21:11:12                 highly## 8  676509769562251264 iPhone 2015-12-14 21:11:12              respected## 9  676509769562251264 iPhone 2015-12-14 21:11:12                   golf## 10 676509769562251264 iPhone 2015-12-14 21:11:12                odyssey## # ... with 8,743 more rows

特朗普推文中最常见的词汇是什么?

现在,让我们考虑Android中相对于iPhone最常见的单词,反之亦然。

我们将使用对数比值比的简单度量,为每个单词计算如下:

android_iphone_ratios <- tweet_words %>%  count(word, source) %>%  filter(sum(n) >= 5) %>%  spread(source, n, fill = 0) %>%  ungroup() %>%  mutate_each(funs((. + 1) / sum(. + 1)), -word) %>%  mutate(logratio = log2(Android / iPhone)) %>%  arrange(desc(logratio))source) %>%  filter(sum(n) >= 5) %>%  spread(source, n, fill = 0) %>%  ungroup() %>%  mutate_each(funs((. + 1) / sum(. + 1)), -word) %>%  mutate(logratio = log2(Android / iPhone)) %>%  arrange(desc(logratio))

哪些最有可能来自Android?哪些可能来自iPhone呢?

一些观察:

  • 大多数主题标签都来自iPhone。的确,从特朗普的Android几乎没有鸣叫包含主题标签,与像一些罕见的例外这一个。(这是真的,因为我们过滤掉引用的“转推”,因为特朗普有时会引用这样包含主题标签的推文)。

  • 像“加入”和“明天”这样的词,以及像“晚上7点”这样的词也来自iPhone。iPhone显然负责像这样的活动公告(“明天晚上7点在德克萨斯州休斯敦加入我!”)

  • 许多“情绪激动”的词语,如“糟糕”,“疯狂”,“弱”和“愚蠢”,在Android上更为常见。这支持了最初的假设,即这是“愤怒”帐户。

情绪分析:特朗普的推文比他的竞选更为负面

由于我们观察到Android和iPhone推文之间的情绪差异,让我们尝试量化它。我们将与NRC Word-Emotion Association 词典合作,该词典可从tidytext包中获得,该词汇将词语与10种情绪联系起来:积极,消极,愤怒,期待,厌恶,恐惧,快乐,悲伤,惊讶信任

nrc <- sentiments %>%  filter(lexicon == "nrc") %>%  dplyr::select(word, sentiment)nrc
## # A tibble: 13,901 x 2##           word sentiment##          <chr>     <chr>## 1       abacus     trust## 2      abandon      fear## 3      abandon  negative## 4      abandon   sadness## 5    abandoned     anger## 6    abandoned      fear## 7    abandoned  negative## 8    abandoned   sadness## 9  abandonment     anger## 10 abandonment      fear## # ... with 13,891 more rows## # A tibble: 13,901 x 2##           word sentiment##          <chr>     <chr>## 1       abacus     trust## 2      abandon      fear## 3      abandon  negative## 4      abandon   sadness## 5    abandoned     anger## 6    abandoned      fear## 7    abandoned  negative## 8    abandoned   sadness## 9  abandonment     anger## 10 abandonment      fear## # ... with 13,891 more rows

为了衡量Android和iPhone推文的情绪,我们可以计算每个类别中的单词数量:

sources <- tweet_words %>%  group_by(source) %>%  mutate(total_words = n()) %>%  ungroup() %>%  distinct(id, source, total_words)by_source_sentiment <- tweet_words %>%  inner_join(nrc, by = "word") %>%  count(sentiment, id) %>%  ungroup() %>%  complete(sentiment, id, fill = list(n = 0)) %>%  inner_join(sources) %>%  group_by(source, sentiment, total_words) %>%  summarize(words = sum(n)) %>%  ungroup()head(by_source_sentiment)
## # A tibble: 6 x 4##    source    sentiment total_words words##     <chr>        <chr>       <int> <dbl>## 1 Android        anger        4901   321## 2 Android anticipation        4901   256## 3 Android      disgust        4901   207## 4 Android         fear        4901   268## 5 Android          joy        4901   199## 6 Android     negative        4901   560## # A tibble: 6 x 4##    source    sentiment total_words words##     <chr>        <chr>       <int> <dbl>## 1 Android        anger        4901   321## 2 Android anticipation        4901   256## 3 Android      disgust        4901   207## 4 Android         fear        4901   268## 5 Android          joy        4901   199## 6 Android     negative        4901   560

例如,我们看到Android推文中4901个单词中的321个与“愤怒”相关。接着,我们想要衡量Android账户相对于iPhone账户使用的结果。由于这是计数数据,我们可以使用 Poisson test 来衡量差异:

library(broom)sentiment_differences <- by_source_sentiment %>%  group_by(sentiment) %>%  do(tidy(poisson.test(.$words, .$total_words)))sentiment_differences
## Source: local data frame [10 x 9]## Groups: sentiment [10]## ##       sentiment estimate statistic      p.value parameter  conf.low##           <chr>    <dbl>     <dbl>        <dbl>     <dbl>     <dbl>## 1         anger 1.492863       321 2.193242e-05  274.3619 1.2353162## 2  anticipation 1.169804       256 1.191668e-01  239.6467 0.9604950## 3       disgust 1.677259       207 1.777434e-05  170.2164 1.3116238## 4          fear 1.560280       268 1.886129e-05  225.6487 1.2640494## 5           joy 1.002605       199 1.000000e+00  198.7724 0.8089357## 6      negative 1.692841       560 7.094486e-13  459.1363 1.4586926## 7      positive 1.058760       555 3.820571e-01  541.4449 0.9303732## 8       sadness 1.620044       303 1.150493e-06  251.9650 1.3260252## 9      surprise 1.167925       159 2.174483e-01  148.9393 0.9083517## 10        trust 1.128482       369 1.471929e-01  350.5114 0.9597478## # ... with 3 more variables: conf.high <dbl>, method <fctr>,## #   alternative <fctr>## Source: local data frame [10 x 9]## Groups: sentiment [10]## ##       sentiment estimate statistic      p.value parameter  conf.low##           <chr>    <dbl>     <dbl>        <dbl>     <dbl>     <dbl>## 1         anger 1.492863       321 2.193242e-05  274.3619 1.2353162## 2  anticipation 1.169804       256 1.191668e-01  239.6467 0.9604950## 3       disgust 1.677259       207 1.777434e-05  170.2164 1.3116238## 4          fear 1.560280       268 1.886129e-05  225.6487 1.2640494## 5           joy 1.002605       199 1.000000e+00  198.7724 0.8089357## 6      negative 1.692841       560 7.094486e-13  459.1363 1.4586926## 7      positive 1.058760       555 3.820571e-01  541.4449 0.9303732## 8       sadness 1.620044       303 1.150493e-06  251.9650 1.3260252## 9      surprise 1.167925       159 2.174483e-01  148.9393 0.9083517## 10        trust 1.128482       369 1.471929e-01  350.5114 0.9597478## # ... with 3 more variables: conf.high <dbl>, method <fctr>,## #   alternative <fctr>

我们以95%的置信区间对其进行可视化:

因此,与iPhone账户相比,特朗普的Android账户使用了大约40-80%的与厌恶,悲伤,恐惧,愤怒和其他“负面”情绪相关的词汇。(积极情绪在统计学上显着不同。)

我们特别感兴趣的是哪些词语在情绪上引起了不同的看法。让我们考虑每个类别中变化最大的单词:

这证实了许多注释为负面情绪的词语(除了“犯罪”和“恐怖分子”之类的一些例外)在特朗普的Android推文中比竞选的iPhone推文更常见。

结论

最近纽约人关于特朗普的“交易艺术”的代笔作家托尼·施瓦茨的文章让我着迷。特别感兴趣的是施瓦茨如何模仿特朗普的声音和哲学:

在他的日记中,施瓦茨描述了试图让特朗普的声音在书中令人满意的过程。他写道,这是一种“诡计”,模仿特朗普的直率,断断续续,不道歉的交付,同时让他看起来几乎是孩子气的...... 回顾现在的文本,施瓦茨说,“我创造了一个比特朗普实际上更胜一筹的角色。”

像任何新闻一样,数据新闻最终是关于人类的兴趣,而且我感兴趣的是一个人:谁在写这些iPhone推文?

来自iPhone的大部分推文都是相当温和的声明。但考虑这些案例,都来自iPhone:

这些推文肯定听起来像我们都知道的特朗普。也许我们上面的分析并不完整:- 可能特朗普有时(但很少)从iPhone上发推文(也许是口述,或者当他自己的电池耗尽时才使用它)。但是,如果我们的假设是正确的,并且这些不是由候选人撰写的 - 只是有人试图听起来像他一样?

或者像这样的推文(也就是iPhone),捍卫特朗普的口号 - 但听起来不像他写的东西?

关于特朗普的精神状态已经写了很多。但我真的宁愿进入这个匿名职员的头脑,他的工作是模仿特朗普独特的节奏(“非常悲伤!”),或者对数百万粉丝进行积极的调整。他是一个真正的信徒,还是只是政治机器中的一个齿轮,他可以将任何主流吸引力混合到@realDonaldTrump混合物中?就像Tony Schwartz一样,他有一天会后悔自己的参与吗?

长按订阅更多精彩▼

特朗普推文的文本分析相关推荐

  1. 情感分析朴素贝叶斯_朴素贝叶斯推文的情感分析

    情感分析朴素贝叶斯 Millions of tweets are posted every second. It helps us know how the public is responding ...

  2. 特朗普近百条推文,被 Twitter 标记为「不实消息」

    By 超神经 内容提要:自从 2016 年美国大选之后,各社交平台因虚假消息误导选民而备受批评.近几年来,Twitter 在消除虚假信息上投入了大力气,最近晒出了今年的成果. 关键词:Twitter ...

  3. lstm 文本分类_带有lstm和单词嵌入的灾难推文上的文本分类

    lstm 文本分类 This was my first Kaggle notebook and I thought why not write it on Medium too? Ť他是我第一次Kag ...

  4. 一条推文卖出 290 万美元天价?网友:我竟是隐藏的富翁

    ‍‍ 作者 | Carol 出品 | CSDN(ID:CSDNnews) 近日,Twitter联合创始人&CEO杰克·多西(Jack Dorsey)以290万美元的价格出售了他的第一条推文. ...

  5. 本公众号最新的单细胞推文目录

    本公众号最新的单细胞推文目录: 分析 单细胞分析实录(1): 认识Cell Hashing 单细胞分析实录(2): 使用Cell Ranger得到表达矩阵 单细胞分析实录(3): Cell Hashi ...

  6. 如何使用PHP机器学习分析推文情感

    This article was peer reviewed by Wern Ancheta. Thanks to all of SitePoint's peer reviewers for maki ...

  7. 爬虫取中间文本_小小爬虫批量抓取微信推文里的图片

    哈喽,大家好,今天给大家分享一个特别特别小的爬虫案例! 爬取微信推文中的图片!!!! 有人说,这有啥用,,,,万一人家推文是放的是以图片的方式放的某个PPT的内容呢,你想把它弄下来,咋整,就是爬取啦. ...

  8. 【文本分类】基于BERT预训练模型的灾害推文分类方法、基于BERT和RNN的新闻文本分类对比

    ·阅读摘要: 两篇论文,第一篇发表于<图学学报>,<图学学报>是核心期刊:第二篇发表于<北京印刷学院学报>,<北京印刷学院学报>没有任何标签. ·参考文 ...

  9. IRIS 2021 技术文档 First Look 30 -- 使用 InterSystems 产品进行文本分析

    本技术概览( First Look )介绍了 InterSystems IRIS® 数据平台 支持使用 Natural Language Processing(NLP,自然语言处理 )文本分析的能力, ...

最新文章

  1. Tomcat 系统架构与设计模式,第 1 部分: 工作原理
  2. mysql right syntax_mysql the right syntax to use near 'not null comment '身份'
  3. 设置一个双色球脚本(2)并带颜色输出
  4. Fragment销毁时replace和add两个方法的区别
  5. 整理了Linux常用命令变量
  6. java api 获取jvm实例_JVMTI那些事——和Java相互调用
  7. 蓝桥杯 ADV-71 算法提高 判断回文
  8. iOS--视频播放器之ZFPlayer
  9. AutoRunner 功能自动化测试项目实训之常见问题(十)
  10. 笔记本拔插电源黑屏问题
  11. 工业级4g无线路由器_工业级4g无线路由器厂家品牌
  12. activiti画流程图、部署、启动、审批、驳回
  13. 翡润年华教你肉眼鉴别翡翠ABC
  14. 影响蜘蛛抓取的因素有哪些?
  15. 计算机许可管理器服务器名称是什么意思,部署 - 安装后的许可证服务器是什么?...
  16. 华为鸿蒙系统怎么退出,鸿蒙系统准备就绪,华为将退出安卓联盟,进度能赶超安卓吗?...
  17. Uniswap V2里的手续费换算
  18. 33种经典图表类型总结,轻松玩转数据可视化
  19. 推广引流秘籍:利用小红书精准加客源
  20. ios 关于https://itunes.apple.com/lookup获取appstore版本不及时的问题

热门文章

  1. Educational Codeforces Round 84 (Rated for Div. 2) A~ ESZU cf集训
  2. python使用函数的目的_在Python 3.x中经常看到定义函数有一个单独的 * 参数?定义这样参数的目的是?怎样对其取值呢?...
  3. oracle数据库 gbk,oracle 数据库编码转换(转GBK) | 学步园
  4. java初始化一个链表_Java 链表(LinkNode)的简单操作:初始化,遍历,插入,删除等...
  5. easyui中的tree数据使用说明
  6. win10下硬盘安装CentOS7
  7. 从CES Asia 2017看智能家居的发展趋势
  8. javascript 实现页面显示当前时间 动态读秒
  9. Discuz NT 架构剖析之Config机制
  10. 自己写的一个tomcat发布脚本