中文情感分析 - SnowNLP
情感分析(Sentiment analysis,SA),又称倾向性分析、意见抽取(Opinion extraction)、意见挖掘(Opinion mining)、情感挖掘(Sentiment mining)、主观分析(Subjectivity analysis)
情感分析是对带有情感色彩的主观性文本进行分析、处理、归纳和推理的过程
情感分析的目的是为了找出说话者/作者在某些话题上或者针对一个文本两极观点的态度。这个态度或许是他或她的个人判断或是评估,也许是他当时的情感状态(就是说,作者在做出这个言论时的情绪状态),或是作者有意向的情感交流(就是作者想要读者所体验的情绪)
文本情感分析的应用非常广泛,如网络舆情风险分析,信息预测等。如通过Twitter用户情感预测股票走势,电影票房、选举结果等,均是将公众情绪与社会事件对比,发现一致性,并用于预测
首先安装SnowNLP中文情感分析库:
pip install snownlp
SnowNLP(Simplified Chinese Text Processing),是一个python语言编写的类库,可以方便的处理中文文本内容,其开发受到了TextBlob的启发
In [1]:
import pandas as pd
import matplotlib.pyplot as plt
from snownlp import SnowNLP
数据载入
In [2]:
df = pd.read_excel('data/饭店留言数据.xlsx')
df
Out[2]:
comments | date | |
---|---|---|
0 | 这辈子最爱吃的火锅,一星期必吃一次啊!最近才知道他家还有免费鸡蛋羹………………炒鸡好吃炒鸡嫩... | 2017-05-14 16:00:00 |
1 | 第N次来了,还是喜欢?…… 从还没上A餐厅的楼梯开始,服务员已经在那迎宾了,然... |
2017-05-10 16:00:00 |
2 | 大姨过生日,姐姐定的这家A餐厅的包间,服务真的是没得说,A餐厅的服务也是让我由衷的欣赏,很久... | 2017-04-20 16:00:00 |
3 | A餐厅的服务哪家店都一样,体贴入微。这家店是我吃过的排队最短的一家,当然也介于工作日且比较晚... | 2017-04-25 16:00:00 |
4 | 因为下午要去天津站接人,然后我倩前几天就说想吃A餐厅,然后正好这有,就来这吃了。 来的... |
2017-05-21 16:00:00 |
5 | A餐厅是我们的定点单位,单位大聚小聚都来这,所以享受VIP待遇,来了不用等位。这的菜品新鲜,... | 2017-05-05 16:00:00 |
6 | 这两天风特别大,家里也没什么可吃的,外卖也不知道吃什么!又懒得出去,发现好久没吃火锅啦!灵机... | 2017-04-22 16:00:00 |
7 | A餐厅真的是天津每一个店我都来过无数次了! 今天觉得我拍的图很好看hhhh于是就来发条... |
2017-05-20 16:00:00 |
8 | 今天又来到新开路的A餐厅,食材还是非常新鲜,羔羊肉味道鲜美,墨鱼滑味道新鲜!我们一家三口吃的... | 2017-05-12 16:00:00 |
9 | 服务态度一如既往的好,看我东西多,主动帮忙提东西,所有的服务员都主动打招呼,非常热情。我点的... | 2017-05-07 16:00:00 |
10 | 服务好赞!外送小哥实际A餐厅自己配的,送之前一个电话说别急已经在送的路上,送到后也一个电话说... | 2017-04-10 16:00:00 |
11 | 服务一如既往的这么赞、论食材是火锅中的精粹,论服务也绝对是龙头老大!人多最爱来吃A餐厅了、每... | 2017-04-23 16:00:00 |
12 | 一直特别特别特别爱A餐厅真的服务太贴心了细节决定一切呀用餐的时候接了个电话无意中跟朋友说今天... | 2017-05-07 16:00:00 |
13 | 服务没的说啊,非常的周到啊,从始至终不用自己喊服务员,主动的倒饮料,帮我们下肉,吃完还给我们... | 2017-05-14 16:00:00 |
14 | 口味还不错?点了一份蛋炒饭,加荷包蛋?溏心的。捞派捞面?还不错,菌汤番茄?的都好吃。炸馒头一... | 2017-05-14 16:00:00 |
15 | 话说我真的很久很久没有吃A餐厅了,朋友想吃,我俩就过来了。她喜欢番茄锅,所以我们点了牛油麻辣... | 2017-04-25 16:00:00 |
16 | 提前预订的因为孩子生日孩子们又喜欢那的口味服务我就不都说了一如既往的优质每位服务员态度都是那... | 2017-04-27 16:00:00 |
17 | A餐厅新开路店是在天津所有A餐厅门店当中,我最愿意光临的,因为这里停车方便,排队人也不像其他... | 2017-03-17 16:00:00 |
18 | 再次来享受A餐厅的服务,真是好,等位的时候可以下棋等餐,而且有美甲做,需要排队很久,柠檬水不... | 2017-05-06 16:00:00 |
19 | 服务和味道一如既往的好,主要最爱吃他家DIY的小料!这次还用手机扫了个公众平台用一楼的照片打... | 2017-04-14 16:00:00 |
20 | A餐厅的服务一直很好,光顾很多次了,这次去是小伙伴们帮忙预定,为我庆生,A餐厅的工作人员还提... | 2017-05-21 16:00:00 |
21 | 今天下班,和朋友说好去吃A餐厅?,到那没有排队就可以直接进去吃??,点了它这新品,红皮土豆,... | 2017-04-14 16:00:00 |
22 | 1.环境还好,算中等。 2.服务不错,越来越好,有生日布置,原来送小蛋糕,现在改果盘中... |
2017-05-04 16:00:00 |
23 | A餐厅火锅 上周五带对象去吃的,我本人对火锅不是特别爱吃,吃不了辣,对象喜欢吃辣的,就... |
2017-03-16 16:00:00 |
24 | 这次是在情人节当天过去的,以前从来没在情人节正日子出来过,不是因为没有男朋友,而是感觉哪哪人... | 2017-02-20 16:00:00 |
25 | 一直喜欢A餐厅,去过其他店,这次陪父母来他家体验。排队等待时服务员很贴心的送来小吃,很温馨。... | 2017-05-22 16:00:00 |
26 | 家门口经常去服务没的说环境也挺好的 | 2017-05-24 01:50:00 |
数据预处理
In [3]:
df.info()
RangeIndex: 27 entries, 0 to 26
Data columns (total 2 columns):
comments 27 non-null object
date 27 non-null datetime64[ns]
dtypes: datetime64[ns](1), object(1)
memory usage: 512.0+ bytes
In [4]:
text = df.loc[0, 'comments']
text
Out[4]:
'这辈子最爱吃的火锅,一星期必吃一次啊!最近才知道他家还有免费鸡蛋羹………………炒鸡好吃炒鸡嫩啊!!新出的红皮土豆也好好吃,还有炸酥肉,秒杀任何火锅店啊!服务员太可爱,告诉我们半份豆花是4块儿,一份豆花是6块儿,点两个半份比较合适,太实在了哈哈哈,每次妈妈说开心果好吃服务员都给我们打包带走??希望A餐厅早日出咖喱锅,期待ing……'
In [7]:
a = SnowNLP(text)
a.sentiments
Out[7]:
0.4244401030222834
将所有数据打分
In [9]:
def aaa(x):
return SnowNLP(x).sentiments
grade = df['comments'].apply(aaa)
grade # 科学计数法
Out[9]:
0 4.244401e-01
1 4.506914e-01
2 1.000000e+00
3 1.182003e-01
4 8.712261e-01
5 9.980202e-01
6 9.820584e-01
7 6.392747e-03
8 4.267672e-02
9 6.235047e-01
10 1.965386e-04
11 9.999997e-01
12 9.999998e-01
13 9.999515e-01
14 9.999862e-01
15 1.215408e-03
16 1.000000e+00
17 9.827555e-01
18 8.931110e-01
19 9.998846e-01
20 1.000000e+00
21 9.100772e-01
22 9.270364e-01
23 9.999957e-01
24 6.334066e-08
25 9.999988e-01
26 6.348401e-01
Name: comments, dtype: float64
将分数合并会原表格
In [11]:
df['grade'] = grade
df.head()
Out[11]:
comments | date | grade | |
---|---|---|---|
0 | 这辈子最爱吃的火锅,一星期必吃一次啊!最近才知道他家还有免费鸡蛋羹………………炒鸡好吃炒鸡嫩... | 2017-05-14 16:00:00 | 0.424440 |
1 | 第N次来了,还是喜欢?…… 从还没上A餐厅的楼梯开始,服务员已经在那迎宾了,然... |
2017-05-10 16:00:00 | 0.450691 |
2 | 大姨过生日,姐姐定的这家A餐厅的包间,服务真的是没得说,A餐厅的服务也是让我由衷的欣赏,很久... | 2017-04-20 16:00:00 | 1.000000 |
3 | A餐厅的服务哪家店都一样,体贴入微。这家店是我吃过的排队最短的一家,当然也介于工作日且比较晚... | 2017-04-25 16:00:00 | 0.118200 |
4 | 因为下午要去天津站接人,然后我倩前几天就说想吃A餐厅,然后正好这有,就来这吃了。 来的... |
2017-05-21 16:00:00 | 0.871226 |
计算指标
In [12]:
# 平均值
df['grade'].mean()
Out[12]:
0.6987503312852683
In [13]:
# 中位数
df['grade'].median()
Out[13]:
0.9270364310550024
In [14]:
# 快速统计
df['grade'].describe()
Out[14]:
count 2.700000e+01
mean 6.987503e-01
std 4.008801e-01
min 6.334066e-08
25% 4.375657e-01
50% 9.270364e-01
75% 9.999909e-01
max 1.000000e+00
Name: grade, dtype: float64
基础结论:中位数比平均值高很多,说明有少量异常低的评分拉低了均值
可视化
In [16]:
df2 = df[['date', 'grade']].set_index('date').sort_index()
df2.head()
Out[16]:
grade | |
---|---|
date | |
2017-02-20 16:00:00 | 6.334066e-08 |
2017-03-16 16:00:00 | 9.999957e-01 |
2017-03-17 16:00:00 | 9.827555e-01 |
2017-04-10 16:00:00 | 1.965386e-04 |
2017-04-14 16:00:00 | 9.998846e-01 |
看分数分布情况,直方图最合适
In [17]:
df2.plot.hist()
Out[17]:
少量数据,柱状图也可以
In [18]:
df2.plot.bar()
Out[18]:
In [19]:
plt.scatter(df2.index, df2['grade'])
Out[19]:
In [20]:
plt.boxplot(
df['grade'], # 数据
showmeans = True, # 是否显示平均值,默认不显示
widths = 0.5, # 柱子宽度
vert = True, # 默认True纵向,False横向
patch_artist = True, # 是否填充颜色
boxprops = {'facecolor':'#ffff00','color':'green'}, # 箱体样式
)
plt.grid(linewidth=0.2)
以分数排序,查看打分准确率
In [22]:
df3 = df.sort_values(by='grade', ascending=False)
df3
Out[22]:
comments | date | grade | |
---|---|---|---|
2 | 大姨过生日,姐姐定的这家A餐厅的包间,服务真的是没得说,A餐厅的服务也是让我由衷的欣赏,很久... | 2017-04-20 16:00:00 | 1.000000e+00 |
20 | A餐厅的服务一直很好,光顾很多次了,这次去是小伙伴们帮忙预定,为我庆生,A餐厅的工作人员还提... | 2017-05-21 16:00:00 | 1.000000e+00 |
16 | 提前预订的因为孩子生日孩子们又喜欢那的口味服务我就不都说了一如既往的优质每位服务员态度都是那... | 2017-04-27 16:00:00 | 1.000000e+00 |
12 | 一直特别特别特别爱A餐厅真的服务太贴心了细节决定一切呀用餐的时候接了个电话无意中跟朋友说今天... | 2017-05-07 16:00:00 | 9.999998e-01 |
11 | 服务一如既往的这么赞、论食材是火锅中的精粹,论服务也绝对是龙头老大!人多最爱来吃A餐厅了、每... | 2017-04-23 16:00:00 | 9.999997e-01 |
25 | 一直喜欢A餐厅,去过其他店,这次陪父母来他家体验。排队等待时服务员很贴心的送来小吃,很温馨。... | 2017-05-22 16:00:00 | 9.999988e-01 |
23 | A餐厅火锅 上周五带对象去吃的,我本人对火锅不是特别爱吃,吃不了辣,对象喜欢吃辣的,就... |
2017-03-16 16:00:00 | 9.999957e-01 |
14 | 口味还不错?点了一份蛋炒饭,加荷包蛋?溏心的。捞派捞面?还不错,菌汤番茄?的都好吃。炸馒头一... | 2017-05-14 16:00:00 | 9.999862e-01 |
13 | 服务没的说啊,非常的周到啊,从始至终不用自己喊服务员,主动的倒饮料,帮我们下肉,吃完还给我们... | 2017-05-14 16:00:00 | 9.999515e-01 |
19 | 服务和味道一如既往的好,主要最爱吃他家DIY的小料!这次还用手机扫了个公众平台用一楼的照片打... | 2017-04-14 16:00:00 | 9.998846e-01 |
5 | A餐厅是我们的定点单位,单位大聚小聚都来这,所以享受VIP待遇,来了不用等位。这的菜品新鲜,... | 2017-05-05 16:00:00 | 9.980202e-01 |
17 | A餐厅新开路店是在天津所有A餐厅门店当中,我最愿意光临的,因为这里停车方便,排队人也不像其他... | 2017-03-17 16:00:00 | 9.827555e-01 |
6 | 这两天风特别大,家里也没什么可吃的,外卖也不知道吃什么!又懒得出去,发现好久没吃火锅啦!灵机... | 2017-04-22 16:00:00 | 9.820584e-01 |
22 | 1.环境还好,算中等。 2.服务不错,越来越好,有生日布置,原来送小蛋糕,现在改果盘中... |
2017-05-04 16:00:00 | 9.270364e-01 |
21 | 今天下班,和朋友说好去吃A餐厅?,到那没有排队就可以直接进去吃??,点了它这新品,红皮土豆,... | 2017-04-14 16:00:00 | 9.100772e-01 |
18 | 再次来享受A餐厅的服务,真是好,等位的时候可以下棋等餐,而且有美甲做,需要排队很久,柠檬水不... | 2017-05-06 16:00:00 | 8.931110e-01 |
4 | 因为下午要去天津站接人,然后我倩前几天就说想吃A餐厅,然后正好这有,就来这吃了。 来的... |
2017-05-21 16:00:00 | 8.712261e-01 |
26 | 家门口经常去服务没的说环境也挺好的 | 2017-05-24 01:50:00 | 6.348401e-01 |
9 | 服务态度一如既往的好,看我东西多,主动帮忙提东西,所有的服务员都主动打招呼,非常热情。我点的... | 2017-05-07 16:00:00 | 6.235047e-01 |
1 | 第N次来了,还是喜欢?…… 从还没上A餐厅的楼梯开始,服务员已经在那迎宾了,然... |
2017-05-10 16:00:00 | 4.506914e-01 |
0 | 这辈子最爱吃的火锅,一星期必吃一次啊!最近才知道他家还有免费鸡蛋羹………………炒鸡好吃炒鸡嫩... | 2017-05-14 16:00:00 | 4.244401e-01 |
3 | A餐厅的服务哪家店都一样,体贴入微。这家店是我吃过的排队最短的一家,当然也介于工作日且比较晚... | 2017-04-25 16:00:00 | 1.182003e-01 |
8 | 今天又来到新开路的A餐厅,食材还是非常新鲜,羔羊肉味道鲜美,墨鱼滑味道新鲜!我们一家三口吃的... | 2017-05-12 16:00:00 | 4.267672e-02 |
7 | A餐厅真的是天津每一个店我都来过无数次了! 今天觉得我拍的图很好看hhhh于是就来发条... |
2017-05-20 16:00:00 | 6.392747e-03 |
15 | 话说我真的很久很久没有吃A餐厅了,朋友想吃,我俩就过来了。她喜欢番茄锅,所以我们点了牛油麻辣... | 2017-04-25 16:00:00 | 1.215408e-03 |
10 | 服务好赞!外送小哥实际A餐厅自己配的,送之前一个电话说别急已经在送的路上,送到后也一个电话说... | 2017-04-10 16:00:00 | 1.965386e-04 |
24 | 这次是在情人节当天过去的,以前从来没在情人节正日子出来过,不是因为没有男朋友,而是感觉哪哪人... | 2017-02-20 16:00:00 | 6.334066e-08 |
好评
In [23]:
df3.iloc[0, 2]
Out[23]:
0.9999999999992604
In [24]:
df3.iloc[0, 0]
Out[24]:
'大姨过生日,姐姐定的这家A餐厅的包间,服务真的是没得说,A餐厅的服务也是让我由衷的欣赏,很久没吃A餐厅了,发现很多肉的价钱确实是不便宜,底料也都是很全面的,锅底点了四种,商家很聪明,为了怕锅底沸了串味,就那个白萝卜挡在锅底的拼缝中间,真的是很聪明,最爱吃的还是番茄锅底,菌汤也很好喝,但选了一个麻辣锅来涮鸭血、鸭舌,麻辣可以有效地来调和鸭肉的腥味。中途工作人员推着蛋糕过来唱生日歌送祝福,还为我们布置了生日快乐我的房间,摆了气球,真的是让老人家很感动也很开心,真的很赞!'
差评
In [25]:
df3.iloc[-1, 2]
Out[25]:
6.334065716373516e-08
In [26]:
df3.iloc[-1, 0]
Out[26]:
'这次是在情人节当天过去的,以前从来没在情人节正日子出来过,不是因为没有男朋友,而是感觉哪哪人都多,所以特意错开,这次实在是馋A餐厅了,所以赶在正日子也出来了,从下午四点多的时候我看排号就排到一百多了,我从家开车过去得堵的话一个小时,我一看提前两个小时就在网上先排着号了,差不多我们是六点半到的,到那的时候我看号码前面还有才三十多号,我想着肯定没问题了,等一会就能吃上的,没想到悲剧了,就从我们到那坐到等位区开始,大约是十分二十分一叫号,中途多次我都想走了,哈哈,哎,等到最后早上九点才吃上的,服务员感觉也没以前清闲时周到了,不过这肯定的,一人负责好几桌,今天节日这么多人,肯定是很累的,所以大多也都是我自己跑腿,没让服务员给弄太多,就虾滑让服务员下的,然后环境来说感觉卫生方面是不错,就是有些太吵了,味道还是一如既往的那个味道,不过A餐厅最人性化的就是看我们等了两个多小时,上来送了我们一张打折卡,而且当次就可以使用,这点感觉还是挺好的,不愧是A餐厅,就是比一般的要人性化,不过这次就是选错日子了,以后还是得提前预约,要不就别赶节日去,太火爆了!'
In [27]:
df3.iloc[-2, 2]
Out[27]:
0.0001965386178448547
In [28]:
df3.iloc[-2, 0]
Out[28]:
'服务好赞!外送小哥实际A餐厅自己配的,送之前一个电话说别急已经在送的路上,送到后也一个电话说用餐时服务需要依然可以随时联系,简直不能再赞了!!帮做好一切开餐前准备工作,坐等锅开涮着吃?
除了点的麻酱,备注的需要辣油和蒜泥也一一满足,其中点的虾滑也提供了搭配蘸料,鸭血提供了搭配干料,另外送来凉菜和新鲜水果。各种满足。'
In [29]:
df3.iloc[-3, 2]
Out[29]:
0.0012154080772626141
In [30]:
df3.iloc[-3, 0]
Out[30]:
'话说我真的很久很久没有吃A餐厅了,朋友想吃,我俩就过来了。她喜欢番茄锅,所以我们点了牛油麻辣和番茄双拼,现在真是贵啊,锅底就要84元,然后又点了牛肉羊肉各半分,还有一些蔬菜,吃的饱饱的。
自助的小菜没有吃,但是西瓜不错很甜。工作日的中午人不多,服务太热情了有点受不了,其实就想和朋友聊聊天,服务员不停加水,哎!!!'
结论
准确率比瞎猜高,但达不到人工打分准确率
SnowNLP库的训练基准数据是基于电商销售产品训练的,对饭店留言数据的打分准确率一般
做情感分析最好用户自行实现(网站增加打分功能,用户自行打分)