'''读取数据'''
import pandas as pd
import numpy as np
inputfile = 'chapter15/demo/data/huizong.csv'
data = pd.read_csv(inputfile, encoding='utf-8')
data.head()
Id | 已采 | 已发 | 电商平台 | 品牌 | 评论 | 时间 | 型号 | PageUrl | |
---|---|---|---|---|---|---|---|---|---|
0 | 1 | True | False | 京东 | AO | 挺好的 ,安装人员很负责 指的夸奖 | 2014/8/26 9:07 | AO史密斯(A.O.Smith) ET300J-60 电热水器 60升 | http://s.club.jd.com/productpage/p-1008025-s-0... |
1 | 2 | True | False | 京东 | AO | 自己安装的,感觉蛮好。后续追加。 | 2014/10/17 14:24 | AO史密斯(A.O.Smith) ET300J-60 电热水器 60升 | http://s.club.jd.com/productpage/p-1008025-s-0... |
2 | 3 | True | False | 京东 | AO | \n\nAO史密斯(A.O.Smith) ET300J-60 电热水器 60升 还没安装 | 2014/11/12 13:36 | AO史密斯(A.O.Smith) ET300J-60 电热水器 60升 | http://s.club.jd.com/productpage/p-1008025-s-0... |
3 | 4 | True | False | 京东 | AO | 还没装,等安装之后再来吧,为装修备的货。 | 2014/11/16 0:04 | AO史密斯(A.O.Smith) ET300J-60 电热水器 60升 | http://s.club.jd.com/productpage/p-1008025-s-0... |
4 | 5 | True | False | 京东 | AO | 大小刚刚好,安装收了140材料费,活接、弯头啥的。试机顺利,16度加热到30度用了6分钟左右... | 2014/11/11 8:11 | AO史密斯(A.O.Smith) ET300J-60 电热水器 60升 | http://s.club.jd.com/productpage/p-1008025-s-0... |
'''抽取美的的评论'''
outputfile = 'chapter15/demo/tmp2/meidi.txt'
data = data[['评论']][data['品牌'] == '美的']
data.to_csv(outputfile, index=False, header=False)
data.head()
评论 | |
---|---|
95898 | 京东商城信得过,买的放心,用的省心、安心、放心! |
95899 | 给公司宿舍买的,上门安装很快,快递也送的及时,不错的。给五分吧 |
95900 | 美的值得信赖,质量不错 |
95901 | 不错不错的哦,第一次在京东买这些产品,感觉相当好 |
95902 | 很满意,水方一晚上都还是热的早上还能再洗, |
1. 文本去重
'''文本去重'''
outputfile = 'chapter15/demo/tmp2/meidi_1.txt'
l1 = len(data)
data = pd.DataFrame(data['评论'].unique(), columns=data.columns)
l2 = len(data)
data.to_csv(outputfile, index=False, header=False, encoding='utf-8')
print('删除了%s条评论' % (l1 - l2))
删除了2725条评论
data.head()
评论 | |
---|---|
0 | 京东商城信得过,买的放心,用的省心、安心、放心! |
1 | 给公司宿舍买的,上门安装很快,快递也送的及时,不错的。给五分吧 |
2 | 美的值得信赖,质量不错 |
3 | 不错不错的哦,第一次在京东买这些产品,感觉相当好 |
4 | 很满意,水方一晚上都还是热的早上还能再洗, |
2. 机械压缩去词,可以删除评论开头和结尾重复的词语,如“为什么为什么为什么安装费这么贵”压缩为“为什么安装费这么贵”,“真的挺好挺好挺好挺好”压缩为“真的挺好”
'''定义机械压缩去词函数'''
def compress(string):
string = string.strip() # 删除换行符
str_list = list(string) # 分隔字符为列表
s1 = [str_list[0]] # 初始化 s1 列表为第一个字符
s2 = []
del_idx = []
for i in range(1, len(str_list)):
# 判断当前字符是否为最后一个字符
if i == len(str_list) - 1: # 当前字符为最后一个字符,进行压缩判断
if s2 != []:
s2.append(str_list[i])
if s1 == s2: # 如果 s1 和 s2 重复,则将需删除的索引加入 del_idx 中
# print('{}为最后一个字符,发现重复,删除的索引为{}~{}'.format(i, i-len(s2), i-1))
del_idx.extend(range(i-len(s2), i))
else: # 不重复则什么也不做
# print('{}为最后一个字符,未发现重复'.format(i))
pass
# 当前字符不是最后一个字符,判断当前字符和 s1 的第一个字符是否相同
elif s1[0] == str_list[i]: # 当前字符和 s1 的第一个字符相同,判断 s2 是否为空
if s2 == []: # s2 为空,将该字符放入 s2
# print('{}和 s1 相同,s2 为空,放入 s2'.format(i))
s2 = [str_list[i]]
# s2 不为空,进行压缩判断
elif s1 == s2: # 如果 s1 和 s2 重复,则将需删除的索引加入 del_idx 中,然后清空 s2
# print('{}和 s1 相同,s2 不为空,发现重复,删除的索引为{}~{}'.format(i, i-len(s2), i-1))
del_idx.extend(range(i-len(s2), i))
s2 = [str_list[i]]
else: # 不重复,清空两个列表,将字符放入 s1
# print('{}和 s1 相同,s2 不为空,未发现重复,清空列表,放入 s1'.format(i))
s1 = [str_list[i]]
s2 = []
# 当前字符和 s1 的第一个字符不同,进行压缩判断
elif (s1 == s2) & (len(s2) >= 2): # 如果 s1 和 s2 重复,且字符数大于等于2,则将需删除的索引加入 del_idx 中
# print('{}和 s1 不相同,发现重复且字符数大于等于2,删除的索引为{}~{}'.format(i, i-len(s2), i-1))
del_idx.extend(range(i-len(s2), i))
# 清空两个列表,将字符放入 s1
s1 = [str_list[i]]
s2 = []
elif s1 != s2: # 如果 s1 和 s2 不重复,判断 s2 是否为空
if s2 == []: # s2 为空,放入 s1
# print('{}和 s1 不相同,s2 为空,放入 s1'.format(i))
s1.append(str_list[i])
#print(len(s1))
else: # s2 不为空,放入 s2
# print('{}和 s1 不相同,s2 不为空,放入 s2'.format(i))
s2.append(str_list[i])
#print(len(s2))
else:
#print(i)
pass
# 删除字符,从后往前删,避免索引变化
del_idx = sorted(del_idx)
for t in range(len(del_idx)-1, -1, -1):
del str_list[del_idx[t]]
new_str = ''.join(str_list)
return new_str
# 字符串倒序函数
sort = lambda x: ''.join(list(x)[::-1])
# 开头去重
data = pd.DataFrame(data['评论'].astype(str).apply(compress))
# 倒序,然后开头去重(即末尾去重)
data = pd.DataFrame(data['评论'].astype(str).apply(sort))
data = pd.DataFrame(data['评论'].astype(str).apply(compress))
# 还原
data = pd.DataFrame(data['评论'].astype(str).apply(sort))
# 删除 4 字及以下的评论
l1 = len(data)
data = data[data['评论'].apply(lambda x: len(x) > 4)]
l2 = len(data)
print('删除了%s条评论' % (l1 - l2))
删除了993条评论
# 保存数据
outputfile = 'chapter15/demo/tmp2/meidi_2.txt'
data.to_csv(outputfile, index=False, header=False, encoding='utf-8')
'''删除前缀评分代码'''
import pandas as pd
inputfile1 = 'chapter15/demo/data/meidi_jd_process_end_负面情感结果.txt'
inputfile2 = 'chapter15/demo/data/meidi_jd_process_end_正面情感结果.txt'
outputfile1 = 'chapter15/demo/tmp2/meidi_neg.txt'
outputfile2 = 'chapter15/demo/tmp2/meidi_pos.txt'
data1 = pd.read_csv(inputfile1, encoding='utf-8', header=None)
data2 = pd.read_csv(inputfile2, encoding='utf-8', header=None)
data1 = pd.DataFrame(data1[0].str.replace('.*?\d+?\\t ', ''))
data2 = pd.DataFrame(data2[0].str.replace('.*?\d+?\\t ', ''))
data1.to_csv(outputfile1, index=False, header=False, encoding='utf-8')
data2.to_csv(outputfile2, index=False, header=False, encoding='utf-8')
'''分词代码'''
import jieba
outputfile1 = 'chapter15/demo/tmp2/meidi_neg_cut.txt'
outputfile2 = 'chapter15/demo/tmp2/meidi_pos_cut.txt'
mycut = lambda x: ' '.join(jieba.cut(x))
data1 = data1[0].apply(mycut)
data2 = data2[0].apply(mycut)
data1.to_csv(outputfile1, index=False, header=False, encoding='utf-8')
data2.to_csv(outputfile2, index=False, header=False, encoding='utf-8')
'''LDA 代码'''
stoplist = 'chapter15/demo/data/stoplist.txt' # 停用词表
stop = pd.read_csv(stoplist, encoding='utf-8', header=None, sep='tipdm')
# sep 设置分隔词,由于 csv 默认使用半角逗号作为分隔词,该词刚好在停用词表中,因此会导致出错,所以需要设置一个不存在的分隔词
stop = [' ',''] + list(stop[0]) # pandas 会自动过滤空格,添加进去
neg = pd.DataFrame(data1)
pos = pd.DataFrame(data2)
neg[1] = neg[0].apply(lambda x: x.split(' ')) # 分隔
neg[2] = neg[1].apply(lambda x: [i for i in x if i not in stop]) # 判断是否在停用词表中
pos[1] = pos[0].apply(lambda x: x.split(' '))
pos[2] = pos[1].apply(lambda x: [i for i in x if i not in stop])
from gensim import corpora, models
# 负面主题分析
neg_dict = corpora.Dictionary(neg[2]) # 建立词典
neg_corpus = [neg_dict.doc2bow(i) for i in neg[2]] # 建立语料库
neg_lda = models.LdaModel(neg_corpus, num_topics=3, id2word=neg_dict) # LDA 模型训练
for i in range(3):
print(neg_lda.print_topic(i))
print('\n')
print('***************************************************************')
# 正面主题分析
pos_dict = corpora.Dictionary(pos[2]) # 建立词典
pos_corpus = [pos_dict.doc2bow(i) for i in pos[2]] # 建立语料库
pos_lda = models.LdaModel(pos_corpus, num_topics=3, id2word=pos_dict) # LDA 模型训练
for i in range(3):
print(pos_lda.print_topic(i))
print('\n')
0.038*"安装" + 0.024*"买" + 0.022*"热水器" + 0.013*"师傅" + 0.013*"美的" + 0.011*"京东" + 0.009*"问题" + 0.008*"一个" + 0.007*"东西" + 0.006*"售后"
0.033*"安装" + 0.020*"好" + 0.016*"买" + 0.016*"知道" + 0.015*"热水器" + 0.014*"不错" + 0.013*"加热" + 0.011*"n" + 0.008*"使用" + 0.008*"挺"
0.047*"安装" + 0.028*"不错" + 0.014*"安装费" + 0.013*"好" + 0.012*"热水器" + 0.011*"师傅" + 0.011*"美的" + 0.011*"有点" + 0.010*"不好" + 0.010*"东西"
***************************************************************
0.059*"安装" + 0.021*"师傅" + 0.013*"一个" + 0.013*"热水器" + 0.013*"加热" + 0.011*"买" + 0.011*"好" + 0.011*"美的" + 0.010*"有点" + 0.008*"安装费"
0.101*"不错" + 0.096*"好" + 0.038*"安装" + 0.023*"买" + 0.022*"送货" + 0.021*"东西" + 0.020*"挺" + 0.016*"热水器" + 0.016*"很快" + 0.016*"速度"
0.021*"美的" + 0.017*"n" + 0.016*"值得" + 0.015*"京东" + 0.013*"买" + 0.012*"信赖" + 0.011*"热水器" + 0.011*"问题" + 0.011*"安装" + 0.010*"品牌"
源代码及数据文件参考:https://github.com/Raymone23/Data-Mining