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

作者: 古柳_Deserts_X | 来源:发表于2018-06-13 23:14 被阅读174次

    上一篇文章乱炖数据之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。

    相关文章

      网友评论

      本文标题:乱炖“简书交友”数据之代码(1)

      本文链接:https://www.haomeiwen.com/subject/igmseftx.html