如何用Python和R对故事情节做情绪分析?让语言人性化!
烦恼
追剧是个令人苦恼的事情。
就拿刚刚播完第7季的《权力的游戏》来说,每周等的时候那叫一个煎熬,就盼着周一能提早到来。
你可能抓狂了,觉得这是个不可能完成的任务,就如同英谚所云:
You can't have your cake and eat it too.
- 愤怒(anger)
- 期待(anticipation)
- 厌恶(disgust)
- 恐惧(fear)
- 喜悦(joy)
- 悲伤(sadness)
- 惊讶(surprise)
- 信任(trust)
准备
数据
我们首先需要找到的是来源数据。作为例子,我们选择了《权利的游戏》第三季的第9集,名字叫做"The Rains of Castamere"。
你可以到这个网址下载这一集的剧本。
我建议你选择中国的镜像,这样连接速度更快。清华大学的镜像就不错。
请根据你的操作系统平台选择其中对应的版本下载。我选择的是macOS版本,下载得到pkg文件。双击就可以安装。
安装了基础包之后,我们继续安装集成开发环境RStudio。下载地址为这里。
我们打开看看内容。
往下翻页,我们找到了剧本正文正式开始的标记 Opening Credits 。
翻到文本的结尾,我们可以看到剧本结束的标记 End Credits 。
我们回到主页面下,新建一个Python的Notebook。点击右方的New按钮,选择Python 2。
数据正确读入。下面我们依照刚才浏览中发现的标记把正文以外的文本内容去掉。
先去掉开头的非剧本正文内容。
data = data.split('Opening Credits]')[1]
再次打印,可以看见现在从正文开头了。
print(data)
下面我们同样处理结尾部分。
data = data.split('[End Credits')[0]
打印出来试试看。
print(data)
拖动到尾部。
lines = data.split(' ')
然后给每一行加上行号。
myrows = []
num = 1
for line in lines:
myrows.append([num, line])
num = num + 1
我们看看前三行的行号是否已经正常添加。
myrows[:3]
好了,既然数据框已经做好了。下面我们把它转换成为csv格式,以便于R来读取和处理。
df.to_csv('data.csv', index=False)
我们打开data.csv文件,可以看到数据如下:
数据清理和准备工作结束,下面我们用R进行分析。
分析
RStudio可以提供一个交互环境,帮我们执行R命令并即时反馈结果。
打开RStudio之后,选择File->New,然后从以下界面中选择 R Notebook。
然后,我们就有了一个R Notebook的模板。模板附带一些基础使用说明。
我们尝试点击编辑区域(左侧)代码部分(灰色)的运行按钮。
立即就可以看到绘图的结果了。
另外我们还可以点击菜单栏上的Preview按钮,来看整个儿代码的运行结果。
RStudio为我们生成了HTML文件,我们的文字说明、代码和运行结果图文并茂呈现出来。
好了,熟悉了环境后,我们该实际操作运行自己的代码了。咱们把左侧编辑区的开头说明区保留,把全部正文删除,并且把文件名改成有意义的名字,例如 emotional-analysis 。
数据有了,下面我们需要准备分析用的包。这里我们需要用到4个包,请执行以下语句安装。
这里原先的行号依然被保留。我们可以看到每一个词来自于哪一行,这有利于下面我们对行甚至段落单位进行分析。
以第1行为例,包含“期待”的词有1个,包含“恐惧”的有1个,包含“信任”的有3个。
如果我们以1行为单位分析情感变化,粒度过细。鉴于整个剧本包含了几百行文字,我们以5行作为一个基础单位,来进行分析。
结果是丰富多彩的,可惜看不大清楚。为了区别不同情绪,我们调用 facet_wrap 函数,把不同情绪拆开,分别绘制。
嗯,这张图看着就舒服多了。
不过这张图也会给我们造成一些疑惑。按照道理来说,每一段落的内容里,包含单词数量大致相当。结尾部分情感分析结果里面,正向和负向几乎同时上升,这就让人很不解。是这里的几行太长了,还是出了什么其他的问题呢?
我们再来看看负向情感词汇吧。
看了这个结果,就更令人沮丧不已了——同样的一个lord,竟然既被当成了正向,又被当成了负向词汇。词典标注者太不负责任了吧!
别着急。出现这样的情况,是因为我们做分析时少了一个重要步骤——处理停用词。对于每一个具体场景,我们都需要使用停用词表,把那些可能干扰分析结果的词扔出去。
这次好多了,起码解释情绪可以自圆其说了。我们再看看那些负向情感词汇。
比起之前,也有很大进步。
做好了基础的修订工作,下面我们来重新作图吧。我们把停用词表加进去,并且还用 filter语句把情感属性删除掉了。因为我们分析的对象是情绪(emotion),而不是情感(sentiment)。
在这一集的结尾,多种情绪混杂交织——欢快的气氛陡然下降,期待与信任在波动,厌恶在不断上涨,恐惧与悲伤陡然上升,愤怒突破天际,交杂着数次的惊讶……
你可能会纳闷儿,情绪怎么可能这么复杂?是不是分析又出问题了?
还真不是,这一集的故事,有个另外的名字,叫做《红色婚礼》。