我的信仰是科学的唯物史观,虽然一直觉得爷爷是伟人,但是没有系统钻研小本本,所以似懂非懂,好在有睡前消息这个节目,可以时不时的聆听到半个世纪前的伟人智慧。


一、读取数据

睡前消息是我最喜欢看的节目, 基本上隔两天不看睡不踏实。本次分享,不涉及观点之争,纯属技术玩乐。

数据集 | 马前卒工作室睡前消息文稿汇总

import pandas as pd


bed_df = pd.read_csv('bedtime_news.csv', converters={'date': str})
bed_df.date = pd.to_datetime(bed_df.date)
bed_df.head()


#数据集起始日期
print(str(bed_df['date'].min())[:10])
print(str(bed_df['date'].max())[:10])

Run

2019-07-12
2022-11-29

#数据集含有的节目数
len(bed_df)

Run

522


二、准备工作

2.1 自定义词典

  • 科学、技术
  • 社会化抚养
  • 债务、独山县
  • 中医、以岭药业

将感兴趣的词加入到jieba自定义词典中,防止被错分。

import jieba

diywords = ['科学', '技术', '社会化抚养', '债务', '独山县', '毛选', '唯物', '社会实验']
for word in diywords:
    jieba.add_word(word)

2.2 word_in_context

在这里定义了一个word_in_context函数,可以查看某些关键词上下文环境。

import jieba
import re
from nltk.tokenize import word_tokenize
import pandas as pd
import warnings


def word_in_context(text, keywords, window=3, lang='chinese'):
    if lang=='chinese':
        words = jieba.lcut(text.lower())
    else:
        try:
            words = word_tokenize(text.lower())
        except:
            warnings.warn("你应该安装nltk和对应的nltk_data, 请看B站https://www.bilibili.com/video/BV14A411i7DB")
            words = text.lower().split(' ')
    keywords = [w.lower() for w in keywords]
    kw_idxss = [[i for i, x in enumerate(words) if x == keyword] for keyword in keywords]
    rows = []
    for keyword, kw_idxs in zip(keywords, kw_idxss):
        for idx in kw_idxs:
            half = int((window-1)/2)
            start = max(0, idx - half)
            end = min(len(words), idx + half + 1)
            row = {'keyword': keyword, 
                   'context': ''.join(words[start: end]) if lang=='chinese' else ' '.join(words[start: end])
                      }
            rows.append(row)
    df = pd.DataFrame(rows)
    return df


#测试【打算】前后上下文5个单词
word_in_context(text='根本没打算过真抓到人,当然也不打算付钱。转发推送:还有一个话题', 
                keywords=['打算'], 
                window=5, 
                lang='chinese')

2.3 词云图

pip install pyecharts==2.0.1

def plot_wordcloud(df, title):
    import pyecharts.options as opts
    from pyecharts.charts import WordCloud
    text = ''.join(df['context'])
    text = ''.join(re.findall('[\u4e00-\u9fa5]+', text))
    words = jieba.lcut(text)
    words = [w for w in words if len(w)>=2]
    wordfreqs = []
    for word in set(words):
        freq = words.count(word)
        wordfreqs.append((word, freq))
    wordfreqs = sorted(wordfreqs, key=lambda k:k[1], reverse=True)
    wordfreqs = [(w, str(f)) for w,f in wordfreqs]
    cloud = WordCloud()
    cloud.add(series_name="", data_pair=wordfreqs, word_size_range=[20, 100])
    cloud.set_global_opts(title_opts=opts.TitleOpts(title=title, 
                                                    title_textstyle_opts=opts.TextStyleOpts(font_size=23)),
                          tooltip_opts=opts.TooltipOpts(is_show=True))
    cloud.render('{}.html'.format(title))
    return cloud.render_notebook()



三、话题分析

相比LDA机器学习算法的晦涩难懂,其实可以用word_in_context对指定关键词进行定位和分析,数据处理的过程清晰透明。

3.1 Topic-社会化抚养

dfs = []
for idx, row in bed_df.iterrows():
    df = word_in_context(text=row['text'], 
                            keywords=['社会化抚养'], 
                            window=50)
    df['date'] = row['date']
    dfs.append(df)
    
topic_df = pd.concat(dfs, axis=0)
topic_df


#涉及该主题的节目数
len(topic_df['date'].unique())

Run

65

#占比
len(topic_df['date'].unique())/len(bed_df)

Run

0.12452107279693486

在咱们这个数据集中,睡前消息500多期节目中,有65期谈及社会化抚养的,比例12%。


plot_wordcloud(df=topic_df, title='社会化抚养')


3.2 Topic-科学技术

dfs2 = []
for idx, row in bed_df.iterrows():
    df = word_in_context(text=row['text'], 
                            keywords=['科学', '技术'], 
                            window=50)
    df['date'] = row['date']
    dfs2.append(df)
    
topic_df2 = pd.concat(dfs2, axis=0)
topic_df2


#涉及该主题的节目数
len(topic_df2['date'].unique())

Run

411

#占比
len(topic_df2['date'].unique())/len(bed_df)

Run

0.7873563218390804

在咱们这个数据集中,睡前消息500多期节目中,有411期谈及社会化抚养的,比例79%。


plot_wordcloud(df=topic_df, title='科学技术')


3.3 科学社会

面对社会问题,睡前消息倡导科学社会实验, 也喜欢讲毛选语录, 两者所涉及的是唯物的观点,科学社会的观点。放在一起试试

dfs3 = []
for idx, row in bed_df.iterrows():
    df = word_in_context(text=row['text'], 
                            keywords=['毛选', '唯物', '社会实验'], 
                            window=100)
    df['date'] = row['date']
    dfs3.append(df)
    
topic_df3 = pd.concat(dfs3, axis=0)
topic_df3


#涉及该主题的节目数
len(topic_df3['date'].unique())

Run

14

len(topic_df3['date'].unique())/len(bed_df)

Run

0.02681992337164751

plot_wordcloud(df=topic_df3, title='科学社会')


广而告之