1月9日被誉为中国最牛的产品经理张小龙做了微信的年度演讲[1],引爆朋友圈。
1月10日采铜写了篇《张小龙四个小时的演讲没有讲什么?》[2],又引爆朋友圈。在现在几乎所有人张口就谈“认知升级”、“底层逻辑”等词的时代,这篇文章用数据阐述了张小龙在演讲想表达什么。我觉得特别好玩的是,有很多大家都在说的词,耳朵里听出老茧的词,他一个字都没提。为什么呢?也许他的词典里根本没有这样的词,也许有但是他觉得根本不重要。反正,从这些他没有用的词中,我看到了值得思考的东西。
统计文章的词频,给我提供了一个新的思路,能不能用python统计高频词呢?肯定是可以的。先放出一张最终结果图,有一个更直观的体验。下面就是我们如何一步一步实现这样的过程,Here we go!
这里使用python的jieba库(感谢开发)对中文进行分词。
首先需要安装分词库。打开终端,输入以下命令行。1$ pip install jieba若提示没有安装pip,则自行在网络中搜索pip 并安装。
将演讲(或其他)内容保存复制为report.txt,与py程序文件放在同一文件夹下,在终端运行以下程序[3-6]:1
2
3
4
5
6
7
8
9
10
11
12
13
14from collections import Counter
import jieba # 导入jieba库
f = open('report.txt').read() # 打开report.txt文档
words = list([word for word in jieba.cut(f, cut_all=False) if len(word) >= 2]) # 分词
data = dict(Counter(words).most_common(50)) # 统计词频,并以Dictionary的方式存储在data中,选择前50个高频词
# 打印高频词和出现次数
for key, value in data.items():
print key.encode('utf-8'), value
此处有几个地方解释一下:
(a) words = list([word for word in jieba.cut(f, cut_all=False) if len(word) >= 2]) 程序较为复杂,将分词功能和 If 判断放在一起。1
2
3
4
5seg_list = jieba.cut("我来到北京清华大学", cut_all=True)
print("Full Mode: " + "/ ".join(seg_list)) # 全模式
seg_list = jieba.cut("我来到北京清华大学", cut_all=False)
print("Default Mode: " + "/ ".join(seg_list))
输出为:1
2> Full Mode: 我/ 来到/ 北京/ 清华/ 清华大学/ 华大/ 大学
> Default Mode: 我/ 来到/ 北京/ 清华大学这里就能发现,设置cut_all = True 会将词语重复判断[7],【清华大学】会被划分成【清华】、【清华大学】、【华大】、【大学】。
(b). 这里利用Counter对象的函数,统计每个词出现的次数,并转化为字典(dict)。
(c). 程序最后的 For 循环将字典(dict)内的内容输出,在key.encode('utf-8')中添加了编码功能,是因为原来格式为unicode所致,对于python中gbk、unicode和str的编码转换,在此不赘述。
OK,以上程序就完成了对内容的高频词统计,也可以在上述程序后添加以下代码,将统计结果保存成txt,若要保存成excel,则需要导入其他python库。1
2
3
4fil = open("stat.txt",'w')
for key, value in data.items():
fil.write("%st%dn" % (key.encode('utf-8'), value))
fil.close()可以尝试将代码中的.encode('utf-8')去掉,改成fw.write("%st%dn" % (key, value)),看看保存的效果哦。
2. 清洗数据
我们已经将长度大于等于2的词统计出来,为展示直观,将这些高频词的词云展示如下:
从这里会发现有些词是没有太多意义的,例如:一个、来说、并且、所以等。下面就需要进行数据清洗,去掉一些无意义的词。由于分词是记录在words这个列表内的,因此需要对words进行清洗。1
2
3
4
5
6
7
8
9
10exclude_words = ["一个","虽然","东西","包括","来说","但是","这个","这里"]
for word in words[:]:
if word.encode('utf-8') in exclude_words[:]:
words.remove(word)
a = []
for word in words:
a.append(word)
txt = r' '.join(a)
这里简单列出列出一些需要清洗的词。通过 For 循环列表元素,用 If 判断词语是否在排除列表中,满足条件则用将其删除[8]。注意,这里列表使用的是for word in words[:]:,而不是for word in words:,这里需要全部遍历。若使用for word in words:的话,会出现不完全遍历。
最后将清洗过的数据以一定格式保存在txt内。
当然也可以反向的方法:如果你有关键词词库,可以查看演讲中是否出现关键词库中的词。1
2
3
4
5
6
7exclude_words = ["一个","虽然","东西","包括","来说","但是","这个","这里"]
for word in words[:]:
if word.encode('utf-8') in exclude_words[:]:
pass
else:
words.remove(word)
既然我们已经将相关词汇统计并清理,下面介绍如何制作词云,数据可视化。
3. 绘制词云
绘制词云需要预先安装wordcloud库1$ pip install wordcloud
之后就可以绘制词云了。1
2
3
4
5
6
7
8
9
10
11
12
13
14from wordcloud import WordCloud
import numpy as np
from PIL import Image
fpath='/Libary/Fonts/Songti.ttc'
wordcloud = WordCloud(font_path= fpath,background_color='white').generate(txt)
wordcloud.to_file("wordcloud.jpg") #保存图片
import matplotlib.pyplot as plt
plt.imshow(wordcloud, interpolation ="bilinear")
plt.axis("off")
plt.show()
绘制词云后,可以将词云添加背景,将词云按照一定的方式排列,将代码修改如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23from wordcloud import WordCloud
import numpy as np
from PIL import Image
fpath='/Libary/Fonts/Songti.ttc'
d = path.dirname(__file__)
color_mask = np.array(Image.open(path.join(d, "background.jpg")))
cloud = WordCloud(
font_path=fpath,
background_color='white',#设置背景色
mask=color_mask, #词云形状
max_words=200, #允许最大词汇
max_font_size=40, #最大号字体
random_state=42
)
wordcloud = cloud.generate(txt)
import matplotlib.pyplot as plt
plt.imshow(wordcloud, interpolation ="bilinear")
plt.axis("off")
plt.show()需要将backgroud.jpg的背景图片放在同一文件夹。
以下放出两张基于 TESLA 和Mixin 背景做的词云。
从上图TESLA背景的词云中可以看出,张小龙的演讲最重要的是“我们”。
注: 本文程序基于Mac OS系统,python2.7。
Logs
2019-01-13: 补充代码、写文章
2019-01-12: 写文章、修改代码
2019-01-11: 运行代码
2019-01-10: 查阅文章