现在,我们得到了一些关于XX商品的评论信息的数据,我们需要对这些评论信息的数据进行情感分析;
环境:Python3.6 + pandas0.24.2
以下文档中使用的文件可在网盘中下载:
comment.csv
链接:https://pan.baidu.com/s/1Q0kBcHRZEzHvYaZvzepYAQ 提取码:cbgh;
stoplist.txt
链接:https://pan.baidu.com/s/1RDs1B7fOJzKWRjB0FBBCxQ 提取码:e3f5;
我的数据文件是在同级目录中
import pandas as pd
data_path = './comment.csv'
df = pd.read_csv(data_path, encoding='gbk')
之后,会获得一个变量名为df
的DataFrame(Pandas中的一种数据结构);
现在,我们可以先打印一下原始数据信息
;
print('原始数据信息:')
print(len(df)) # 长度
print(type(df)) # 数据类型
原始数据信息:
721
<class 'pandas.core.frame.DataFrame'>
------------------
因为我们的数据中可能存在一些缺失值,我们需要清除一下这些缺失值;
运行以下代码:
df = df.dropna() # 消除缺失数据 NaN为缺失数据
print('清除缺失数据后:')
print(len(df))
print(type(df))
print('------------------')
清除缺失数据后:
721
<class 'pandas.core.frame.DataFrame'>
------------------
数据中可能存在一些重复的数据,我们需要去除重复数据;
运行以下代码:
df = pd.DataFrame(df.iloc[:, 0].unique()) # 去掉第一列的重复数据;iloc[:, 0]表示索引每一行的第一列;
print('去重数据后:')
print(len(df))
print('------------------')
去重数据后:
537
------------------
我们发现数据集中有多条重复数据已经被我们清除掉;
现在,我们已经得到一些有效数据;
评论信息中,有一些评论是这样的:“我喜欢喜欢喜欢喜欢喜欢喜欢喜欢这个手机!”;
我们需要对这样的内容进行去除重复字符,我们定义这样一个函数;
def str_unique(raw_str, reverse=False):
"""
比如:我喜欢喜欢喜欢喜欢喜欢喜欢该商品;去掉重复的“喜欢”
:param raw_str:
:param reverse: 是否转置
:return:
"""
if reverse:
raw_str = raw_str[::-1]
res_str = ''
for i in raw_str:
if i not in res_str:
res_str += i
if reverse:
res_str = res_str[::-1]
return res_str
有了这个函数,我们现在对数据应用这个函数,使用apply
方法;
ser1 = df.iloc[:, 0].apply(str_unique) # 这时,因为索引了第一列,所以结果成了Series;
print('df2', type(ser1)) #
df2 = pd.DataFrame(ser1.apply(str_unique, reverse=True)) # 再次生成DataFrame;
print('机械压缩去词后:')
print(len(df2))
print(type(df2))
print('------------------')
df2 <class 'pandas.core.series.Series'>
机械压缩去词后:
537
<class 'pandas.core.frame.DataFrame'>
------------------
由于评论信息中有一些信息是没有参考价值的,我们需要过滤掉这部分信息,比如:评论信息只有4个字符的;
df3 = df2[df2.iloc[:, 0].apply(len) >= 4]
print('短句过滤后:')
print(len(df3))
print('------------------')
短句过滤后:
528
------------------
现在,我们可以对这些数据进行情感分析了;
我们需要用到一个库:snownlp
,这个库是一个情感分析语言处理库;
只需要使用命令pip install snownlp
既可以安装该库;
from snownlp import SnowNLP # 情感分析语言处理库
# 语义积极的概率,越接近1情感表现越积极
coms = df3.iloc[:, 0].apply(lambda x: SnowNLP(x).sentiments)
print('情感分析后:')
positive_df = df3[coms >= 0.9] # 特别喜欢的
negative_df = df3[coms < 0.1] # 不喜欢的
print('特别喜欢的')
print(positive_df)
print('------------------')
print('不喜欢的')
print(negative_df)
情感分析后:
特别喜欢的
0
0 :"再买,半价很优?惠。收到货了包装好看起来高档东西质量没得说不错这个格比我预期的太多产品描...
1 :"挺好吃的⊙▽,评买给老弟说很喜欢必须一直支持这家店官方旗舰嘛?包装 特别是松鼠君服务了多...
3 "满一大箱呢!物流超快,昨晚买的今天就到了赞价格很划算总吃坚果什么也腻小麻花挺好东西呦 客服...
4 "宝贝已收到,物美价廉的时候发现和图片描述一样超级划算!值得再次光顾滴比实体店便宜了半很好不...
...
------------------
不喜欢的
0
512 东西很好,特别是客服鼠硬币的态度我之前不小心用花呗买了一份但发现错支付方式后退款账户余额又订...
515 吐槽一下物流,广东到西为啥要转南京再昌才回宁?慢
535 垃圾东西影都没看到不知道让快递送哪去了客服现在还回辣鸡
...
现在,我们得到了两个DataFrame,一个是positive_df(特别喜欢的),一个是negative_df(不喜欢的);
现在,我们需要对这些评价进行分词分析,分析具体喜欢与不喜欢的原因与关键字;
我们需要用到一个分词库:jieba
分词库;同样,使用命令pip install jieba
即可以安装该库;
import jieba
my_cut = lambda s: ' '.join(jieba.cut(s)) # 自定义简单分词函数
positive_ser = positive_df.iloc[:, 0].apply(my_cut) # 通过“广播机制”分词,加快速度
negative_ser = negative_df.iloc[:, 0].apply(my_cut)
print('大于0.5---正面数据---分词')
print(positive_ser)
print('小于0.5---负面数据---分词')
print(negative_ser)
大于0.5---正面数据---分词
0 : " 再 买 , 半价 很优 ? 惠 。 收到 货 了 包装 好 看起来 高档 东西 质量...
1 : " 挺好吃 的 ⊙ ▽ , 评买 给 老弟 说 很 喜欢 必须 一直 支持 这家 店 官...
3 " 满 一大 箱 呢 ! 物流 超快 , 昨晚 买 的 今天 就 到 了 赞 价格 很 划算...
4 " 宝贝 已 收到 , 物美价廉 的 时候 发现 和 图片 描述 一样 超级 划算 ! 值得...
5 : " 货 很 新鲜 , 吃 起来 好 味道 不错 。 下次 还会 光顾 啊 便宜 , 物流...
6 小宝贝 已 收到 , 物美价廉 的 时候 发现 和 图片 描述 一样 超级 划算 ! 值得 ...
...
小于0.5---负面数据---分词
510 给 朋友 买 的 年货 她 很 喜欢 满意 呦 ? 还有 就是 客服 鼠 木耳 务 态度...
512 东西 很 好 , 特别 是 客服 鼠 硬币 的 态度 我 之前 不 小心 用花 呗 买 了 ...
515 吐槽 一下 物流 , 广东 到 西 为啥 要 转 南京 再昌才 回宁 ? 慢
535 垃圾 东西 影都 没 看到 不 知道 让 快递 送 哪 去 了 客服 现在 还 回辣鸡
现在,我们得到了两个Series,一个是positive_ser
(正面数据分词),一个是negative_ser
(负面数据分词);
这些分词中有一些事停用词
(像:额,但是,等等,喔),我们需要去除这些词;
stop_list = './stoplist.txt' # 我的停用词文件是在同级目录存放
stops = pd.read_csv(stop_list, encoding='gbk', header=None, sep='tipdm', engine='python')
# sep 设置分割词,由于csv默认以半角逗号为分割此,而该词恰好在停用词表中,因此会导致读取出错
# 所以解决办法是手动设置一个不存在的分割词,如tipdm;
stops = [' ', ''] + list(stops[0]) # pandas自动过滤了空格符,这里手动添加
positive_df = pd.DataFrame(positive_ser)
negative_df = pd.DataFrame(negative_ser)
positive_df[1] = positive_df[0].apply(lambda s: s.split(' ')) # 定义一个分割函数,然后用apply广播
positive_df[2] = positive_df[1].apply(lambda x: [i for i in x if i.encode('utf-8') not in stops])
negative_df[1] = negative_df[0].apply(lambda s: s.split(' ')) # 定义一个分割函数,然后用apply广播
negative_df[2] = negative_df[1].apply(lambda x: [i for i in x if i.encode('utf-8') not in stops])
print('去停用词后:positive_df')
print(positive_df)
print('------------------')
print('去停用词后:negative_df')
print(negative_df)
去停用词后:positive_df
0 ... 2
0 : " 再 买 , 半价 很优 ? 惠 。 收到 货 了 包装 好 看起来 高档 东西 质量... ... [:, ", 再, 买, ,, 半价, 很优, ?, 惠, 。, 收到, 货, 了, 包装,...
1 : " 挺好吃 的 ⊙ ▽ , 评买 给 老弟 说 很 喜欢 必须 一直 支持 这家 店 官... ... [:, ", 挺好吃, 的, ⊙, ▽, ,, 评买, 给, 老弟, 说, 很, 喜欢, 必...
3 " 满 一大 箱 呢 ! 物流 超快 , 昨晚 买 的 今天 就 到 了 赞 价格 很 划算... ... [", 满, 一大, 箱, 呢, !, 物流, 超快, ,, 昨晚, 买, 的, 今天, 就...
4 " 宝贝 已 收到 , 物美价廉 的 时候 发现 和 图片 描述 一样 超级 划算 ! 值得... ... [", 宝贝, 已, 收到, ,, 物美价廉, 的, 时候, 发现, 和, 图片, 描述, ...
...
------------------
去停用词后:negative_df
0 ... 2
510 给 朋友 买 的 年货 她 很 喜欢 满意 呦 ? 还有 就是 客服 鼠 木耳 务 态度... ... [给, 朋友, 买, 的, 年货, , , 她, 很, 喜欢, 满意, 呦, ?, 还有, ...
512 东西 很 好 , 特别 是 客服 鼠 硬币 的 态度 我 之前 不 小心 用花 呗 买 了 ... ... [东西, 很, 好, ,, 特别, 是, 客服, 鼠, 硬币, 的, 态度, 我, 之前, ...
515 吐槽 一下 物流 , 广东 到 西 为啥 要 转 南京 再昌才 回宁 ? 慢 ... [吐槽, 一下, 物流, ,, 广东, 到, 西, 为啥, 要, 转, 南京, 再昌才, 回...
535 垃圾 东西 影都 没 看到 不 知道 让 快递 送 哪 去 了 客服 现在 还 回辣鸡 ... [垃圾, 东西, 影都, 没, 看到, 不, 知道, 让, 快递, 送, 哪, 去, 了, ...
进行LDA主题分析
时,我们需要用到一个库:gensim
库,同样使用命令pip install gensim
进行安装;
from gensim import corpora, models
# 正面主题分析
pos_dict = corpora.Dictionary(positive_df[2])
pos_corpus = [pos_dict.doc2bow(i) for i in positive_df[2]]
pos_lda = models.LdaModel(pos_corpus, num_topics=3, id2word=pos_dict)
print('#正面主题分析')
for i in range(3):
print('topic', i)
print(pos_lda.print_topic(i)) # 输出每个主题
# 负面主题分析
neg_dict = corpora.Dictionary(negative_df[2]) # 建立词典
neg_corpus = [neg_dict.doc2bow(i) for i in negative_df[2]] # 建立语料库
neg_lda = models.LdaModel(neg_corpus, num_topics=3, id2word=neg_dict) # LDA 模型训练
print('#负面主题分析')
for i in range(3):
print('topic', i)
print(neg_lda.print_topic(i)) # 输出每个主题
#正面主题分析
topic 0
0.025*"的" + 0.023*"," + 0.016*"很" + 0.014*"给" + 0.013*"喜欢" + 0.012*"" + 0.011*"好" + 0.010*"!" + 0.009*"了" + 0.009*"我"
topic 1
0.034*"," + 0.023*"的" + 0.016*"很" + 0.016*"好" + 0.012*"喜欢" + 0.011*"不错" + 0.010*"。" + 0.009*"!" + 0.008*"挺" + 0.007*"满意"
topic 2
0.024*"" + 0.021*"," + 0.020*"很" + 0.019*"的" + 0.016*"了" + 0.012*"。" + 0.011*"也" + 0.011*"!" + 0.010*"喜欢" + 0.010*"买"
#负面主题分析
topic 0
0.019*"" + 0.013*"," + 0.012*"很" + 0.012*"的" + 0.011*"客服" + 0.009*"买" + 0.009*"!" + 0.008*"给" + 0.008*"小姐" + 0.008*"了"
topic 1
0.018*"," + 0.016*"" + 0.015*"了" + 0.014*"客服" + 0.013*"的" + 0.010*"我" + 0.010*"鼠" + 0.009*"?" + 0.008*"让" + 0.008*"东西"
topic 2
0.014*"很" + 0.014*"客服" + 0.013*"了" + 0.011*"," + 0.011*"" + 0.011*"鼠" + 0.010*"收货" + 0.010*":" + 0.010*"买" + 0.009*"追加"
现在,我们会分别得到关于正面、负面的主题分析;
至此,我们的一个简单的商品情感分析就OK了。