特朗普推文的文本分析


640?wx_fmt=png

导言


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

640?wx_fmt=png

当特朗普祝奥运队好运时,他正在用他的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 = "")


640?wx_fmt=svg

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


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

640?wx_fmt=png


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

640?wx_fmt=svg


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


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

 
 
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 = "")


640?wx_fmt=svg


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

640?wx_fmt=png


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

640?wx_fmt=png

词语比较


现在,我们相信有这两个账户之间的差异,但是,内容上存在着怎样的差异呢?我们将使用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


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

640?wx_fmt=svg


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

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

640?wx_fmt=png

 
 
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呢?

640?wx_fmt=svg

一些观察:

  • 大多数主题标签都来自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%的置信区间对其进行可视化:

640?wx_fmt=svg


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


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

640?wx_fmt=svg


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


结论


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

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

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

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

640?wx_fmt=png


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

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

640?wx_fmt=png


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

长按订阅更多精彩▼

640?wx_fmt=jpeg

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值