手把手教你完成一个数据科学小项目(8):Emoji提取与分布图谱
前言
请先阅读“中国年轻人正带领国家走向危机”,这锅背是不背? 一文,以对“手把手教你完成一个数据科学小项目”系列有个全局性的了解。
本系列代码统一开源在GitHub:DesertsX/gulius-projects ,感兴趣的朋友可以先行 star 哈。
截至目前我们已经完成了数据爬取、数据提取与IP查询、数据异常与清洗、评论数变化情况分析、省份提取与可视化、城市提取与可视化、经纬度获取与BDP可视化。本文将对评论里的
emoji 进行提取,并绘制分布图谱。
读取数据
本次主要关注评论content
列,所以仅读取下面几列数据,忽略其他列。
import pandas as pd
df = pd.read_csv('Sina_Finance_Comments_All_20180811_Cleaned.csv',encoding='utf-8',usecols=['nick','time','content'])
df.head()
提取 emoji
import re
def get_emoji(content):
pattern =re.compile(u"\[[a-zA-Z\u4e00-\u9fa5]+\]")
result=re.findall(pattern,content)
return result
df['emojis_list'] = df['content'].apply(get_emoji)
df.head()
将提取后的列的全部元素转换成列表。
emojis = df['emojis_list'].values.tolist()
emojis
文章所限,仅显示部分输出:
[['[费解]', '[费解]', '[费解]'],
['[允悲]', '[允悲]'],
['[嘿哈]'],
['[笑而不语]'],
['[doge]'],
['[doge]'],
['[泪]'],
['[doge]'],
['[吃瓜]'],
['[允悲]'],
['[二哈]'],
['[笑而不语]', '[笑而不语]'],
['[小黄人得意]'],
['[喵喵]', '[喵喵]'],
['[二哈]'],
['[doge]', '[doge]', '[doge]']]
合并嵌套列表为单一列表,之前文章和代码里已经用过很多次喽。
emojis_list = sum(emojis, [])
emojis_set = list(set(emojis_list))
num = len(emojis_set)
print(num)
print(emojis_set)
统计出emoji共76种:
76
['[打脸]', '[白眼]', '[太开心]', '[允悲]', '[爱你]', '[ok]', '[小黄人坏笑]', '[思考]', '[喵喵]', '[偷笑]', '[悲伤]', '[抱抱]', '[睡]', '[围观]', '[摊手]', '[怒]', '[衰]', '[中国赞]', '[汗]', '[鲜花]', '[小黄人得意]', '[闭嘴]', '[吃惊]', '[吐]', '[阴险]', '[晕]', '[骷髅]', '[憧憬]', '[呵呵]', '[米奇比心]', '[羞嗒嗒]', '[可怜]', '[可爱]', '[挖鼻]', '[哈哈]', '[微笑]', '[挤眼]', '[耶]', '[给力]', '[笑cry]', '[威武]', '[握手]', '[吃瓜]', '[鼓掌]', '[拜拜]', '[失望]', '[坏笑]', '[泪]', '[跪了]', '[嘿哈]', '[费解]', '[哆啦A梦汗]', '[嘻嘻]', '[亲亲]', '[皱眉]', '[哈欠]', '[怒骂]', '[攤手]', '[米奇大哭]', '[笑而不语]', '[黑线]', '[鄙视]', '[good]', '[doge]', '[作揖]', '[費解]', '[猪头]', '[二哈]', '[赞]', '[哼]', '[嘘]', '[生病]', '[哆啦A梦微笑]', '[疑问]', '[污]', '[并不简单]']
emoji 分组统计
from collections import Counter
counter = Counter(emojis_list)
print(counter.most_common())
统计结果,看看大家都喜欢发什么表情:
[('[doge]', 198), ('[二哈]', 148), ('[允悲]', 131), ('[费解]', 100), ('[摊手]', 93), ('[微笑]', 83), ('[笑cry]', 70), ('[吃瓜]', 66), ('[嘻嘻]', 44), ('[吐]', 35), ('[笑而不语]', 34), ('[并不简单]', 33), ('[跪了]', 32), ('[挖鼻]', 25), ('[拜拜]', 24), ('[喵喵]', 20), ('[太开心]', 20), ('[哈哈]', 16), ('[作揖]', 15), ('[泪]', 14), ('[good]', 13), ('[偷笑]', 10), ('[汗]', 10), ('[哆啦A梦汗]', 9), ('[失望]', 9), ('[疑问]', 9), ('[思考]', 8), ('[爱你]', 6), ('[赞]', 6), ('[憧憬]', 6), ('[污]', 6), ('[阴险]', 6), ('[白眼]', 5), ('[黑线]', 5), ('[中国赞]', 5), ('[可爱]', 5), ('[威武]', 5), ('[怒]', 4), ('[鄙视]', 4), ('[米奇大哭]', 4), ('[ok]', 4), ('[皱眉]', 4), ('[費解]', 4), ('[吃惊]', 4), ('[怒骂]', 4), ('[哼]', 4), ('[鲜花]', 4), ('[坏笑]', 3), ('[悲伤]', 3), ('[鼓掌]', 3), ('[攤手]', 3), ('[嘘]', 3), ('[晕]', 3), ('[衰]', 2), ('[呵呵]', 2), ('[抱抱]', 2), ('[小黄人坏笑]', 2), ('[可怜]', 2), ('[哈欠]', 2), ('[打脸]', 2), ('[嘿哈]', 1), ('[小黄人得意]', 1), ('[握手]', 1), ('[挤眼]', 1), ('[耶]', 1), ('[亲亲]', 1), ('[米奇比心]', 1), ('[羞嗒嗒]', 1), ('[围观]', 1), ('[猪头]', 1), ('[闭嘴]', 1), ('[生病]', 1), ('[给力]', 1), ('[哆啦A梦微笑]', 1), ('[骷髅]', 1), ('[睡]', 1)]
emoji 使用情况
y_emojis, x_counts = zip(*counter.most_common())
from pyecharts import Bar
bar = Bar("emoji 使用情况")
bar.add("emoji", y_emojis[:20], x_counts[:20], is_stack=True,is_label_show=True,xaxis_interval=0,xaxis_rotate=-45,xaxis_margin=8)
bar
为方便展示,选出top20:
这回的 emoji 没找到对应表情图,所以无法像当你点开这首《八月》的歌:9400余条评论的分析与挖掘里显示,不过从上一个项目了解如何实现也是一样的:
评论数据
拿出评论数据,方便之后绘制emoji分布图谱。
cmnts_list = df['content'].values.tolist()
cmnts_list
显示部分数据:
['[费解][费解][费解]',
'那你以为不单身就能避免?',
'谢谢',
'想去声援你 结果发不出🌚',
'锅太大,接不住',
'[允悲][允悲]…',
'居然这么说我们年轻人[嘿哈]',
'老了',
'我觉得这条博就是一个笑话……',
'到底该不该透支消费?专家统一一下意见,在线等,急。',
'拜托,我买再多手机穿再多名牌喝再多星巴克都没一个房贷债务高吧。推责任推这么心安理得恶不恶心啊。',
'你们反省一下,不要做历史的罪人[笑而不语]',
将列表合并成一个字符串
cmnts = ' '.join(cmnts_list)
print(len(cmnts))
print(cmnts)
字符串长度为83252。
jieba 分词
在GitHub/jieba分词前,先把上面的emojis_set
里的去掉中括号后的emoji
一个个都添加进自定义的词典,以免分词时被切分开。
此处需注意,如果不去掉中括号[ ]
,直接将整个emojis
添加进词典的话,后续分词时,括号还是会被分开,可能相应的需要修改jieba源码才行(jieba分词与词性标注自定义词典支持特殊字符),但尝试后无果,于是还是采取现在的方案。
jieba/test/test_userdict.py
jieba.del_word('自定义词')
或者在txt
的存好,然后读入jieba.load_userdict("userdict.txt")
import jieba
emoji_drop = []
for emojis in y_emojis:
emoji = emojis[1:-1] # 去掉括号
jieba.add_word(emoji) # 读者可将上一行注释掉,看看分词结果
emoji_drop.append(emoji) # 将去掉括号后的emoji单独保存
words = list(jieba.cut(cmnts))
print(len(words))
print(words)
展示部分分词结果:
54431
['[', '费解', ']', '[', '费解', ']', '[', '费解', ']', ' ', '那', '你', '以为', '不', '单身', '就', '能', '避免', '?', ' ', '谢谢', ' ', '想', '去', '声援', '你', ' ', '结果', '发不出', '🌚', ' ', '锅太大', ',', '接', '不住', ' ', '[', '允悲', ']', '[', '允悲', ']', '…', ' ', '居然', '这么', '说', '我们', '年轻人', '[', '嘿哈', ']', ' ', '老', '了',
去掉括号后的emoji_drop
:
['doge', '二哈', '允悲', '费解', '摊手', '微笑', '笑cry', '吃瓜', '嘻嘻', '吐', '笑而不语', '并不简单', '跪了', '挖鼻', '拜拜', '喵喵', '太开心', '哈哈', '作揖', '泪', 'good', '偷笑', '汗', '哆啦A梦汗', '失望', '疑问', '思考', '爱你', '赞', '憧憬', '污', '阴险', '白眼', '黑线', '中国赞', '可爱', '威武', '怒', '鄙视', '米奇大哭', 'ok', '皱眉', '費解', '吃惊', '怒骂', '哼', '鲜花', '坏笑', '悲伤', '鼓掌', '攤手', '嘘', '晕', '衰', '呵呵', '抱抱', '小黄人坏笑', '可怜', '哈欠', '打脸', '嘿哈', '小黄人得意', '握手', '挤眼', '耶', '亲亲', '米奇比心', '羞嗒嗒', '围观', '猪头', '闭嘴', '生病', '给力', '哆啦A梦微笑', '骷髅', '睡']
NLTK 分布图谱
分布图谱在《当你点开这首《八月》的歌:9400余条评论的分析与挖掘》项目时,就想实现,可惜一直没成功,notebook里保留了尝试的代码,且整个代码太杂乱,需如本系列一样后续拆分开和润色。
也是因缘际会,想本系列项目结束后,下一个系列就来玩玩热门电视剧、热门电影,也罗列了许多切入点,感觉要是能搞出来,还是不错的。这回也先绘制了于正的热门清宫剧《延禧攻略》里的一些主要人物在小说文本中的分布图谱。
扯远了,因为上述尝试成功后,这回也用到emoji的分布上来。虽然评论数据是拼接到一起,因而分布图谱的可解释性一般,权当尝个鲜、玩玩新花样。
import matplotlib.pyplot as plt
%matplotlib inline
import nltk
from nltk.draw.dispersion import dispersion_plot
plt.rcParams['font.sans-serif'] = ['SimHei']
ntext = nltk.Text(words)
ntext.dispersion_plot(emoji_drop[:15])
上面是top15的分布图谱,结合pyecharts的柱形图一起看,风味尤佳:
而全部emoji的分布图谱,纵坐标太密集,但整张图有种说不出的美感,逃......
ntext.dispersion_plot(emoji_drop)
你听说过安利吗?
本系列代码统一开源在GitHub:DesertsX/gulius-projects ,感兴趣的朋友可以先行 star 哈。
本系列文章:
“中国年轻人正带领国家走向危机”,这锅背是不背?
手把手教你完成一个数据科学小项目(1):数据爬取
手把手教你完成一个数据科学小项目(2):数据提取、IP 查询
手把手教你完成一个数据科学小项目(3):数据异常与清洗
手把手教你完成一个数据科学小项目(4):评论数变化情况
手把手教你完成一个数据科学小项目(5):省份提取与可视化
手把手教你完成一个数据科学小项目(6):城市提取与可视化
手把手教你完成一个数据科学小项目(7):经纬度获取与BDP可视化