社交媒体的数据虽然大部分以文字形式呈现,但是其中包含的巨量信息在舆情分析、市场调研乃至政治手腕方面都能够发挥巨大的作用,具有深不可测的潜力,我们在本章节将要学习如何挖掘和分析这些数据,主要目的是复习之前学习的知识并新引入一些函数作为实际操作中的tricks,所以不要认为是单纯的复习课而已。
在这一部分我们需要用到一个新的包:jsonlite. 它可以让我们读取json数据并转换成R语言方便处理的格式。json格式可以理解成一种特殊的表格——字典(dict)格式,它的基本表达形式是“key:value”,表达了本条记录中的某个字段的值为某某。
在终端中输入以下命令安装jsonlite:
1 | install.packages('jsonlite') |
同样地,我们仍然需要用tidyverse处理dataframe数据,所以在教程的最开始我们先导入jsonlite和tidyverse两个包:
1 | library(jsonlite) |
分析懂王的推文
读取json文件并转为dataframe
一切从简,本文主要是为了复习并综合实践前文所述的内容,因此不探讨如何抓取twitter timeline并导出为json格式的文件(假设你有一个助手使用twitterR工具包和twitter的auth key API已经帮你抓好并保存成了json文件,可以在这里下载),我们直接进行读取json文件的操作。
jsonlite包读取json文件的方法如下方代码所示:
1 | # 读取文件DT_tweets.json并且转换为dataframe |
结果如下:
通过字段名称(key)和值(value)可以清晰地看出各列代表的意思,比如前面分别是发送时间、点赞数、粉丝数、推文id、转发数和发送源(设备、客户端或者网站),最右边因为太长了没有显示完整的text <chr>
字段,代表的就是每条推文的文本内容:
如果想取出第一行的文本内容和点赞数,按照原来的方法,代码是:
1 | Trumptweets[1,c('text', 'favourite_count')] |
找出点赞最多的推文
用which.max()
函数找出懂王点赞数最多的tweet。
1 | # 如果这几行看不懂,建议抓紧复习第一篇 |
文本拼接的新方法
之前有学过拼接文本的方法paste()
,而在实际应用中用到cat()
的次数可能更多些。
cat()
的用法其实差不多,区别是可以用sep='separator'
定义拼接的方法,也就是定义分隔符是什么。python里学过\n
是换行符的意思,所以如果我想用换行的方式拼接文本,就在括号内的最后加一个sep="\n"
就可以:
1 | cat('If you forgot how to concatenate strings, this may also help you.','The most popular of Trumps tweets is:', Trumptweets[idx, 'text'], sep="\n") |
输出:
统计关于字数的信息
先计算每篇推文的字数。tidyverse有一个统计字符串长度的函数叫nchar(string_name)
,除此之外,如果第一篇看透了就没啥好讲的哈!直接上代码:
1 | Trumtweets <- Trumptweets %>% # 定义输入和输出 |
接下来计算平均字数,这用到了之前学过的mean()
函数,下面的代码计算出来应该是159.3:
1 | # 计算字数这一列的平均值并保留一位小数 |
最后计算一下超过140字的推文数量,filter()
可以帮助我们按照不等式条件筛选这些推文,而计算数量则可以使用count()
函数实现。
1 | len140 <- Trumptweets %>% |
可以看到一共有3534条推文长达140字以上。懂王的屁话果然多。
分析关键词信息
我们想找出懂王的twitter中有多少关于“boarder”和“immigration”的推文,毕竟这是他老人家永恒的主题。为了去查找包含这些关键词的推文,我们使用函数str_detect()
来进行规则匹配,以我们的任务举例:
1 | ind = str_detect(Trumptweets$text,regex("border|immigration", ignore_case = TRUE)) |
函数的第一部分参数Trumptweets$text
指示了我们搜寻的范围,第二部分参数是一个正则表达式语法regex()
,在这里面的第一个参数"border | immigration"
代表我们想要查找的关键词是“border”或者“immigration”,当然你也可以只写一个词;ignore_case=TRUE/FALSE
代表是否忽略大小写规则,因为懂王很喜欢upper-case关键词发推文,所以我们当然要ignore大小写区别。TRUE和FALSE也可以写成T和F。完整代码如下:
1 | # 输出一个代表每行text是否包含border或者immigration关键词的TRUE/FALSE序列 |
除了像上述这样处理,我们还可以从整个数据集中生成一些包含某个关键词的子集,使用str_subset()
函数可以轻松实现这一点:
1 | # 生成一个关于移民话题的text子集 |
你可能已经注意到了,上面两种函数str_detect()
和str_subset()
只能针对一个列Trumptweets$text
进行操作,而且输出结果丢失了其他列的所有信息。如果既想进行查找,又想保留其他列的信息,可以把str_detect()
函数与filter()
函数结合使用,或者直接作为tibble的下标中的row index。
1 | # 直接作为行标row index(记!得!留!逗!号!) |
注意,条件表达式成立的标准是当其输出为TRUE的时候,即“条件 == TRUE”则成立;而在所有编程语言中默认“条件”等价于“条件 == TRUE”,“!条件”等价于“条件 == FALSE”。举例说明:
1 | # 比如 |
另一个非常有用的函数是str_extract()
,它和str_detect()
的用法相似,唯一不同就是它输出的序列是包含某些关键词的序列中的每一条究竟包含了哪个关键词。如果理解困难的话可以直接看例子:
1 | # 输出每一行包含了mexico、border、wall三个词当中的哪些,如果均不包含则输出NA |
函数str_starts()
和str_ends()
分别代表寻找以某些关键词开头或结尾的文本,其用法和上面的str_subset()
一样,都是输入一列文本+关键词;输出则是一个TRUE或FALSE组成的、和整个数据集等长的序列。
1 | # 检索以“BIG”开头的推文 |
我们发现懂王居然只发了一条BIG开头的推特,非常的鹅妹子嘤。上面这个sum()
函数的用法也可以拓展到其他几个字符串判定函数上,我们举几个简单的例子:
1 | immigration <- sum(str_detect(Trumptweets$text,regex("immigration", ignore_case=T))) |
这几行我刻意不写注释了。聪明的你,一定知道我在干什么。输出是下面这样……算了输出我也不给了,不如你自己来跑一下。
做了这么多分析,也该给老板贡献一点可视化结果了,我们用上次学的ggplot2画个图。首先计算四个数据:
- 包含边境、移民关键词的twitter数量
- 包含工作、失业关键词的twitter数量
- 不包含上述关键词的twitter数量
- 懂王推文的总数(使用
nrow()
函数)
1 | # 包含边境、移民关键词的twitter数量 |
然后分别计算前三个数据占推文总数的百分比,并新建一个data.frame把这三个值放进去以方便画图:
1 | perc_border=(number_border/tot_tweets)*100 |
最后画图:
1 | # 先画条形图,记得fill=labels是按照label区分填充色的意思 |
分析时间轴信息
这里需要一个叫做lubridate的包,我们已经提前装好了,直接引入即可。
这个包有一个函数ymd_hms()
,给它输入一个格式为年-月-日 时:分:秒
时间字符串(你说巧不巧我们刚好是这个,其实这是标准时间格式的一种啦),它可以给你输出一个时间对象。这个时间对象和时间字符串长的差不多,但是最大区别是你可以通过某些方法取出它的日期或者小时等数据,比如我们这里只想分析日期,你就可以用date(对象名称)
函数从时间对象里取出日期。
1 | # 引入lubricate |
我们想要按照日期分组,分析每天的点赞和转发数。使用上文说的date(对象名称)
函数从时间对象里取出日期,用这玩意做一个group_by()
然后用summarize()
包裹sum()
去求一下点赞和转发各自的数量之和。
1 | # 我们直接输出一个新表叫grouped_tweets |
最后,用grouped_tweets这么棒的一个表格画个折线图反应点赞和转发随着日期的变化趋势吧。
1 | # 画个点赞曲线,x轴是日期 |
原来这货真的一直在涨粉吗……?