乱炖“简书交友”数据之代码(1)

上一篇文章乱炖数据之2700余篇“简书交友”专题文章数据的花式玩法发布后,不少人想学习下代码,由于此前不曾在GitHub上开源过,流程还不熟悉,再者本项目中很多尝试性的代码,异常杂乱,因而没有立马公开。在经过删减和整理后,将继续更新出来。

本文主要涉及一些结构化数据的分析,文本数据如词频统计、词云图等等。暂且跳过爬虫部分。 代码见于 GitHub - DesertsX / JianShuJiaoYou,后续LDA主题模型、word2vec词向量、文章照片爬取、人脸识别及颜值打分和照片墙等等更新后也会开源在此项目,欢迎star与指正。

另外先预告下,之后打算开个“Kaggle Kernel 学习系列”,GitHub - DesertsX / Kaggle-Kernel-Learning,主要是翻译和学习下kaggle上优秀的kernels。其中第一篇非常粗糙,还没润色、修改排版布局的notebook可供浏览下,也欢迎关注、star和提供宝贵建议:
https://desertsx.github.io/2018/06/09/1_1_Start_Here-A_Gentle_Introduction/
https://desertsx.github.io/2018/06/09/kaggle-Kernel-01/

结构化数据

文章配图数

读取数据

import pandas as pd
df12 = pd.read_csv('JianShuJiaoYou-All-Data.csv', encoding='utf-8')
df12.head(2)

结果如下:

Page    Num Author  Author_Url  Title   Time    Read    Comment Like    Abstract    Artical_Url Image_Url   Artical_Content
0   1   0   刘秀玲 https://www.jianshu.com/u/470f33ea0c92  我要嫁这样的你 2016-07-25T12:16:39+08:00   109763  4508    5333    你不用太高,比穿三五厘米跟鞋的我看起来不矮就行。我不是小鸟依人的型,累了或者想哭的时候,我愿...   https://www.jianshu.com/p/8de3d395734f  ['//upload-images.jianshu.io/upload_images/125...   你不用太高,比穿三五厘米跟鞋的我看起来不矮就行。我不是小鸟依人的型,累了或者想哭的时候,我愿...
1   1   1   道长是名思维贩子    https://www.jianshu.com/u/92eb338437ee  如果你喜欢一个人,说些什么话让对方也喜欢你呢  2017-10-29T11:42:34+08:00   69260   497 3693    NaN https://www.jianshu.com/p/373d67f7cbce  ['//upload-images.jianshu.io/upload_images/299...   你现在有没有喜欢一个人?

新增Images_Num一列记录每篇文章配图数,但发现数字异常,Image_Url中的每一元素是字符串而非列表。

def images_num(imageslist):
    return len(imageslist)
df12['Images_Num'] = df12.Image_Url.apply(images_num)
df12.head(1)
df12.Images_Num.hist();
output_4_0.png

将字符串转化成 list 格式

eval()函数:可以将 list, tuple, dict 与 string 相互转化

实例:

a = "[[1,2], [3,4], [5,6], [7,8], [9,0]]"
print(a)
print(type(a))
b = eval(a)
print(b)
print(type(b))

输出结果:

[[1,2], [3,4], [5,6], [7,8], [9,0]]
<class 'str'>
[[1, 2], [3, 4], [5, 6], [7, 8], [9, 0]]
<class 'list'>

统计每篇文章配图数的正确方式

def images_num(imageslist):
    return len(eval(imageslist))
df12['Images_Num'] = df12.Image_Url.apply(images_num)
df12.head(1)

分布情况

df12.Images_Num.value_counts()

直方图
分布情况一目了然,文章配图数最多的高达80+。

df12.Images_Num.hist();
output_12_0.png

文章长度 / 字数

粗略统计下每篇文章的长度

def artical_length(artical_content):
    return len(artical_content)
df12['Artical_Length'] = df12.Artical_Content.apply(artical_length)
df12.head(1)
df12.Artical_Length.hist();
output_15_0.png

字数与配图数

看看文章篇幅和配图数之间是否存在某种关系。
seaborn.jointplot

import seaborn as sns
sns.jointplot(x="Artical_Length" , y = "Images_Num" ,data = df12);

改个参数看看

sns.jointplot(x="Artical_Length" , y = "Images_Num" ,data = df12, kind="hex");

评论数与点赞数

由皮尔逊相关系数为0.58可知,评论数与点赞数有一定的线性相关性。

sns_joinplot = sns.jointplot(x="Like" , y = "Comment" ,data = df12);
sns_joinplot.savefig('seaborn_Like_Comment_joinplot.png')

阅读量、评论数与点赞数

python3d画图mpl_toolkits.mplot3d
Matplotlib 绘图教程(3D)

from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
%matplotlib inline

plt.figure(figsize=(12, 7))
ax1 = plt.subplot(111,projection='3d')
x,y,z = df12['Read'],df12['Comment'],df12['Like']
ax1.scatter(x, y, z, s=15)
ax1.set_title('Read-Commnet-Like')
ax1.set_zlabel('Like')
ax1.set_ylabel('Comment')
ax1.set_xlabel('Read')
#plt.show()
output_25_1.png

多变量

看看阅读量、评论数、点赞数、文章篇幅与配图数五个变量之间的相关关系。

Pairplot图

seaborn.pairplot

import matplotlib.pyplot as plt
data = df12[["Read", "Comment", "Like", "Artical_Length","Images_Num"]]
#plt.figure(figsize=(6,4))
g = sns.pairplot(data, palette="husl");
g.savefig('seaborn_pairplot.png')

Heatmap图

seaborn-heatmap

sns.heatmap(data=data.corr(), annot=True, linewidths=0, vmin=-0.2, cmap='RdBu_r');
sns.heatmap( data=data.corr(), annot=True, linewidths=0, vmin=-0.2, cmap='YlGnBu');

文章发布时间

Time列分别提取年份、月份、天、小时等等数据。

def split_time_ymd(timestamp):
    ymd = timestamp.split('T')[0]
    return ymd

def split_time_year(timestamp):
    ymd = timestamp.split('T')[0]
    year = ymd.split('-')[0]
    return year

def split_time_month(timestamp):
    ymd = timestamp.split('T')[0]
    month = ymd.split('-')[1]
    return month

def split_time_day(timestamp):
    ymd = timestamp.split('T')[0]
    day = ymd.split('-')[-1]
    return day

def split_time_hour(timestamp):
    timestamp = timestamp.split('T')[1]
    hour = timestamp[:2]
    return hour

df12['YMD'] = df12.Time.apply(split_time_ymd)
df12['Year'] = df12.Time.apply(split_time_year)
df12['Month'] = df12.Time.apply(split_time_month)
df12['Day'] = df12.Time.apply(split_time_day)
df12['Hour'] = df12.Time.apply(split_time_hour)
df12.head(2)

发文年份

可以和另一专题“今日看点”及一篇旧文里的数据比较:简书=鸡汤?爬取简书今日看点:1916篇热门文章可视化

df12.Year.value_counts()
    2018    1992
    2017     718
    2016       6
    2015       2
    Name: Year, dtype: int64
import matplotlib.pyplot as plt
%matplotlib inline
df12.Year.hist();

发文月份

df12.Month.value_counts()
    04    644
    03    471
    05    444
    02    251
    11    237
    08    205
    01    188
    12     93
    10     93
    09     82
    07      8
    06      2
    Name: Month, dtype: int64
df12.Month.hist();

发文日期

df12.Day.hist();

发文小时

df12.Hour.hist();

ECharts美颜一下:发文小时

上述绘制的发布时间的相关图表都不够美观,于是翻出压箱底的又一篇旧文:图表太丑怎么破,ECharts神器带你飞!

直接套用ECharts图表模板,改下数据和标题等参数就行了,代码参见:简书交友”专题文章之24小时分布情

更多图表见于:ECharts3官网的个人主页

年度月份分布情况

df12.groupby(['Year','Month']).Month.count()
    Year  Month
    2015  04         1
          09         1
    2016  07         2
          08         1
          10         1
          12         2
    2017  01         1
          02         3
          04         1
          06         2
          07         6
          08       204
          09        81
          10        92
          11       237
          12        91
    2018  01       187
          02       248
          03       471
          04       642
          05       444
    Name: Month, dtype: int64

ECharts美颜一下:年度月份

图表太丑怎么破,ECharts神器带你飞!
ECharts3官网的个人主页

echarts_bar_year_month.js里代码复制到该链接后刷新即可:“简书交友”专题文章之年度月份分布情况

文本挖掘

相关旧文一篇:2017,那些出现在日记中的人:简单的文本挖掘

读取数据

import warnings
warnings.filterwarnings("ignore")
import jieba
import numpy as np
import codecs
import pandas as pd  
import matplotlib.pyplot as plt
%matplotlib inline
import matplotlib
matplotlib.rcParams['figure.figsize'] = (10.0, 5.0)
from wordcloud import WordCloud
# https://github.com/amueller/word_cloud/
# conda install -c conda-forge wordcloud

文章内容转化成 list 格式

这段情话还不错的样子,一定是个可爱漂亮的小姐姐写的吧,逃...

content = df12.Artical_Content.values.tolist()
print(len(content), '\n', content[-1])
2718 
我攒了一被子的情话,想要说给你听最近有种很杂碎的感觉,嗯...如果用比喻修辞来说的话,就是已经很久都没有那种写完满满一张纸的感觉,没有看完整整一本书的感觉,没有跑完操场一圈,没有听完一整首歌,也没有睡满整整一夜。总感觉还是缺一点什么。但我有很走心的去想了,可能是因为缺了每一个可爱的你。“如果是去见你,我会跑着去”刚看到这句话的时候,我也很赞同,因为毕竟去见一个想见了很久的人的时候,怎么也按捺不住你你内心的欣喜。到后来,当你真正去见ta的时候,你没有跑,你依然故作镇定的样子,只是你会比平时都迈的步子大一点,你担心你跑起来的样子不那么美观,你担心就算是夏天的微风也还是会把你轻薄的刘海吹乱。你会在意每个细节,你每次都希望你在ta面前是最好的状态。嗨,如果要去见你的话,我不跑着去了,我只想以我最好的状态去见你你像是我被子里的舒服你像是我右手背上的那颗痣你像是我眼角微微泛出来的光你像是我全身每一寸肌肤在呼吸你像是我枕头里的枕芯棉你像是我买过最好看书里的一页你像是我踩着云就可以飞上天你像是我走过的所有路途最想停留的瞬间你是我在夜晚闭上眼最后想到的人你是我在清晨睁开眼最先念起的人你是我的一日三餐你是我的一年四季来不及了不想再浪费时间昨天,今天,明天我还是最喜欢你总有一个人的出现,让我像流沙,像落雪。那些别人在上面划了又划的痕迹,你轻轻一抹,就平了。攒了一被子的情话,以后慢慢数给你听。希望认识更多可爱的人,一起做喜欢的事,写最纯真的字,讲有趣的故事。我是礼雪晶,那么你呢?作者:礼雪晶。“真羡慕你们这么年轻就遇到了这么才华横溢的我。”一个整天与数字对抗却藏了一被子情话的95后女生。愿你的深情不被辜负,你喜欢的人也喜欢你。

jieba 分词

segs = jieba.lcut(content[-1])
print(segs)
for seg in segs:
    if len(seg) > 1:
        print(seg)
['我', '攒', '了', '一', '被子', '的', '情话', ',', '想要', '说', '给', '你', '听', '最近', '有种', '很', '杂碎', '的', '感觉', ',', '嗯', '...', '如果', '用', '比喻', '修辞', '来说', '的话', ',', '就是', '已经', '很久', '都', '没有', '那种', '写', '完', '满满', '一张', '纸', '的', '感觉', ',', '没有', '看', '完', '整整', '一', '本书', '的', '感觉', ',', '没有', '跑', '完', '操场', '一圈', ',', '没有', '听', '完一', '整首歌', ',', '也', '没有', '睡满', '整整', '一夜', '。', '总', '感觉', '还是', '缺', '一点', '什么', '。', '但', '我', '有', '很', '走心', '的', '去', '想', '了', ',', '可能', '是因为', '缺', '了', '每', '一个', '可爱', '的', '你', '。', '“', '如果', '是', '去', '见', '你', ',', '我会', '跑', '着', '去', '”', '刚', '看到', '这句', '话', '的', '时候', ',', '我', '也', '很', '赞同', ',', '因为', '毕竟', '去', '见', '一个', '想见', '了', '很', '久', '的', '人', '的', '时候', ',', '怎么', '也', '按捺不住', '你', '你', '内心', '的', '欣喜', '。', '到', '后来', ',', '当', '你', '真正', '去', '见', 'ta', '的', '时候', ',', '你', '没有', '跑', ',', '你', '依然', '故作', '镇定', '的', '样子', ',', '只是', '你', '会', '比', '平时', '都', '迈', '的', '步子', '大', '一点', ',', '你', '担心', '你', '跑', '起来', '的', '样子', '不', '那么', '美观', ',', '你', '担心', '就算', '是', '夏天', '的', '微风', '也', '还是', '会', '把', '你', '轻薄', '的', '刘海', '吹乱', '。', '你', '会', '在意', '每个', '细节', ',', '你', '每次', '都', '希望', '你', '在', 'ta', '面前', '是', '最好', '的', '状态', '。', '嗨', ',', '如果', '要', '去', '见', '你', '的话', ',', '我', '不', '跑', '着', '去', '了', ',', '我', '只', '想', '以', '我', '最好', '的', '状态', '去', '见', '你', '你', '像是', '我', '被子', '里', '的', '舒服', '你', '像是', '我', '右手', '背上', '的', '那颗', '痣', '你', '像是', '我', '眼角', '微微', '泛出来', '的', '光', '你', '像是', '我', '全身', '每一寸', '肌肤', '在', '呼吸', '你', '像是', '我', '枕头', '里', '的', '枕芯', '棉', '你', '像是', '我', '买', '过', '最好', '看书', '里', '的', '一页', '你', '像是', '我', '踩', '着', '云', '就', '可以', '飞', '上天', '你', '像是', '我', '走过', '的', '所有', '路途', '最想', '停留', '的', '瞬间', '你', '是', '我', '在', '夜晚', '闭上眼', '最后', '想到', '的', '人', '你', '是', '我', '在', '清晨', '睁开眼', '最先', '念起', '的', '人', '你', '是', '我', '的', '一日三餐', '你', '是', '我', '的', '一年四季', '来不及', '了', '不想', '再', '浪费时间', '昨天', ',', '今天', ',', '明天', '我', '还是', '最', '喜欢', '你', '总有', '一个', '人', '的', '出现', ',', '让', '我', '像', '流沙', ',', '像', '落雪', '。', '那些', '别人', '在', '上面', '划', '了', '又', '划', '的', '痕迹', ',', '你', '轻轻', '一抹', ',', '就平', '了', '。', '攒', '了', '一', '被子', '的', '情话', ',', '以后', '慢慢', '数给', '你', '听', '。', '希望', '认识', '更', '多', '可爱', '的', '人', ',', '一起', '做', '喜欢', '的', '事', ',', '写', '最', '纯真', '的', '字', ',', '讲', '有趣', '的', '故事', '。', '我', '是', '礼雪晶', ',', '那么', '你', '呢', '?', '作者', ':', '礼雪晶', '。', '“', '真', '羡慕', '你们', '这么', '年轻', '就', '遇到', '了', '这么', '才华横溢', '的', '我', '。', '”', '一个', '整天', '与', '数字', '对抗', '却', '藏', '了', '一', '被子', '情话', '的', '95', '后', '女生', '。', '愿', '你', '的', '深情', '不', '被', '辜负', ',', '你', '喜欢', '的', '人', '也', '喜欢', '你', '。']
    被子
    情话
    想要
    最近
    有种
    杂碎
    感觉
    ...
    如果
    比喻
    修辞
    来说
    的话
    就是
    已经
    很久
    没有
segment = []
for line in content:
    try:
        segs = jieba.lcut(line)
        for seg in segs:
            if len(seg)>1 and seg != '\r\n':
                segment.append(seg)
    except:
        print(line)
        continue

载入停用词

words_df = pd.DataFrame({"segment": segment})
stopwords_df = pd.read_csv('Stopwords/Chinese_Stopwords.txt',index_col=False, quoting=3,sep="\t",names=['stopwords'], encoding='utf-8') #quoting=3全不引用
stopwords_df.head()

去掉停用词

words_df = words_df[~words_df.segment.isin(stopwords_df.stopwords)]
words_df.head()

统计词频

words_stat = words_df.groupby(by=['segment'])['segment'].agg({"计数": np.size})
words_stat = words_stat.reset_index().sort_values(by=["计数"], ascending=False)
words_stat.head(30)
words_stat.to_csv("JianShuJiaoYou-Words_Segments.csv", encoding='utf-8')

文章内容词云

丑版

wordcloud = WordCloud(font_path='simhei.ttf', background_color='white',max_font_size=80)
word_frequence = {x[0]:x[1] for x in words_stat.head(1000).values}
wordcloud = wordcloud.fit_words(word_frequence)
plt.imshow(wordcloud);
# plt.imsave(path)

自定义背景图 1.0版

简书交友专题 Logo


from scipy.misc import imread
matplotlib.rcParams['figure.figsize'] = (8.0, 8.0)
from wordcloud import WordCloud,ImageColorGenerator
bimg=imread('Logo-1.jpg')
wordcloud=WordCloud(background_color="white",mask=bimg,font_path='simhei.ttf',max_font_size=200)
word_frequence = {x[0]:x[1] for x in words_stat.head(1000).values}
wordcloud=wordcloud.fit_words(word_frequence)
bimgColors=ImageColorGenerator(bimg)
plt.axis("off")
plt.imshow(wordcloud.recolor(color_func=bimgColors));

自定义背景图 2.0版

中古民谣乐团Bloody Woods


from scipy.misc import imread
matplotlib.rcParams['figure.figsize'] = (8.0, 8.0)
from wordcloud import WordCloud,ImageColorGenerator
bimg=imread('中古民谣乐团Bloody Woods.jpg')
wordcloud=WordCloud(background_color="white",mask=bimg,font_path='simhei.ttf',max_font_size=200)
word_frequence = {x[0]:x[1] for x in words_stat.head(1000).values}
wordcloud=wordcloud.fit_words(word_frequence)
bimgColors=ImageColorGenerator(bimg)
plt.axis("off")
plt.imshow(wordcloud.recolor(color_func=bimgColors));

还是太丑

在线词云生成网站:HTML5 Word Cloud

图表太丑怎么破,ECharts神器带你飞
本次词云实例

标题词频、词云

title = df12.Title.values.tolist()
print(len(title), '\n', title[-1])
segment = []
for line in title:
    try:
        segs = jieba.lcut(line)
        for seg in segs:
            if len(seg)>1 and seg != '\r\n':
                segment.append(seg)
    except:
        print(line)
        continue
2718 
攒了一被子的情话,想说给你听
titles_df = pd.DataFrame({"segment": segment})
titles_df = titles_df[~titles_df.segment.isin(stopwords_df.stopwords)]
titles_df.head()
titles_stat = titles_df.groupby(by=['segment'])['segment'].agg({"计数": np.size})
titles_stat = titles_stat.reset_index().sort_values(by=["计数"], ascending=False)
titles_stat.head(30)
wordcloud = WordCloud(font_path='simhei.ttf', background_color='white',max_font_size=80)
word_frequence = {x[0]:x[1] for x in titles_stat.head(1000).values}
wordcloud = wordcloud.fit_words(word_frequence)
plt.imshow(wordcloud);

自定义背景图:Bloody Woods

from scipy.misc import imread
matplotlib.rcParams['figure.figsize'] = (8.0, 8.0)
from wordcloud import WordCloud,ImageColorGenerator
bimg=imread('中古民谣乐团Bloody Woods.jpg')
wordcloud=WordCloud(background_color="white",mask=bimg,font_path='simhei.ttf',max_font_size=200)
word_frequence = {x[0]:x[1] for x in titles_stat.head(1000).values}
wordcloud=wordcloud.fit_words(word_frequence)
bimgColors=ImageColorGenerator(bimg)
plt.axis("off")
plt.imshow(wordcloud.recolor(color_func=bimgColors));

在线词云生成网站:HTML5 Word Cloud

本次实例

简书“今日看点”专题热门文章标题词云

另一专题“今日看点”:简书=鸡汤?爬取简书今日看点:1916篇热门文章可视化

代码:GitHub - DesertsX / JianShuJiaoYou,后续更新LDA主题模型、word2vec词向量、文章照片爬取、人脸识别及颜值打分和照片墙等,敬请期待,欢迎star与指正。

PS:预告下,即将开启“Kaggle Kernel 学习系列”,GitHub - DesertsX / Kaggle-Kernel-Learning,欢迎star。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,732评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,496评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,264评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,807评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,806评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,675评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,029评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,683评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,704评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,666评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,773评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,413评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,016评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,204评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,083评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,503评论 2 343

推荐阅读更多精彩内容