建筑兔零基础自学python记录39|实战词云可视化项目——章节分布10(上)
这次我们来制作《红楼梦》各章节的分布情况:
源代码:
import pandas as pd
import numpy as np
import matplotlib.pyplot as pltdf_hlm = pd.read_csv("hlm.txt", names=["hlm_texts"]).dropna()
filtered_df = df_hlm[~df_hlm.hlm_texts.str.contains(r"第\d卷")]
df_hlm = filtered_df.reset_index(drop=True)hui_mask = df_hlm.hlm_texts.str.match(r'第.+?回')
df_hui = pd.DataFrame(df_hlm.hlm_texts[hui_mask].str.split(' ').tolist(),columns=['Huiname', 'Firstname', 'Secondname'])df_hui['HuiNum'] = np.arange(1, len(df_hui) + 1)
df_hui['AllName'] = df_hui['Firstname'] + ',' + df_hui['Secondname']
df_hui['Start'] = hui_mask[hui_mask].index
df_hui['End'] = df_hui['Start'].shift(-1, fill_value=df_hlm.index[-1] + 1) - 1
df_hui['LineNum'] = df_hui['End'] - df_hui['Start']df_hui['Text'] = df_hui.apply(lambda row: ''.join(df_hlm.hlm_texts[row['Start'] + 1:row['End'] + 1]).replace('\u3000', ''), axis=1)
df_hui['ZiShu'] = df_hui['Text'].str.len()plt.rcParams.update({'font.sans-serif': 'SimHei','savefig.format': 'svg','axes.unicode_minus': False
})plt.figure(figsize=(10, 6))
scatter = plt.scatter(df_hui['LineNum'], df_hui['ZiShu'])
for num, row in df_hui.iterrows():plt.text(row['LineNum'] + 1, row['ZiShu'], row['HuiNum'])plt.xlabel("章节段落数", fontsize=12)
plt.ylabel("章节字数", fontsize=12)
plt.title('《红楼梦》整本书各章节分布情况', fontsize=18)
plt.savefig('plot.svg')
plt.show()
从生成的图和代码中我们都能看到各章节的分布情况和词云无关,这是对于文本解读的一种方式。绘图前我们需要对文本进行一些基本处理。处理之前我们先看一下红楼梦的目录,这是传统的章回体。章回体是中国古代长篇小说的一种叙述体式。其特点是将整部作品分成若干章节,称为 “回” 或 “则”。每回都有相对独立的情节,但又与前后回目紧密相连,共同构成一个完整的故事。每回的开头和结尾往往有一些固定的格式,比如开头常用 “话说”“且说” 等套语,结尾则多以 “欲知后事如何,且听下回分解” 之类的话语来吸引读者继续阅读。
根据目标:制作红楼梦各章节的分布情况。所以在处理时我们需要将每一回分开。
让我们来逐一解读代码:
(1)dropna()去除缺失值(NaN)
在 DataFrame
上使用时:
DataFrame.dropna(axis=0, how='any', thresh=None, subset=None, inplace=False)
在 Series
上使用时:
Series.dropna(axis=0, inplace=False)
axis
:指定删除缺失值的方向,取值可以是0
或'index'
(默认值),表示按行删除;取值为1
或'columns'
时,表示按列删除。how
:指定删除行或列的条件,取值可以是'any'
(默认值),表示只要该行或列中有一个缺失值就删除;取值为'all'
时,表示只有当该行或列中的所有值都是缺失值时才删除。thresh
:一个整数,指定保留行或列所需的非缺失值的最小数量。如果某行或列的非缺失值数量小于thresh
,则将其删除。subset
:一个列标签的列表,用于指定在哪些列中检查缺失值。只有在这些列中存在缺失值的行或列才会被考虑删除。inplace
:一个布尔值,默认为False
。如果设置为True
,则会直接在原对象上进行修改,不返回新的对象;如果设置为False
,则会返回一个新的对象,原对象保持不变。
补充:
Series
:一维的带标签数组。DataFrame
:二维的表格型数据结构,由多个Series
组成。
df_hlm = pd.read_csv("hlm.txt", names=["hlm_texts"]).dropna()
读取红楼梦文本,命名为hlm_texts,去除空行。并且利用pandas将txt转化为一个表格数据
补充:这里的去除空行是一个预操作,在简化文本数据的时候同时方便后续使用正则表达式提取卷、回信息,若存在空行容易导致匹配结果不准确。
(2)DataFrame
数据标签:具有行索引(index)和列索引(columns),可以通过这些索引来访问和操作数据。
DataFrame 对象可以通过 . 操作符加上列名来访问该 DataFrame 中的某一列。如 df.Age
所以 df_hlm.hlm_texts 就是从 df_hlm 这个 DataFrame 中选取名为 hlm_texts 的列。
df["列名"]是表达列
filtered_df = df_hlm[~df_hlm.hlm_texts.str.contains(r"第\d卷")]
df_hlm = filtered_df.reset_index(drop=True)
经过过滤之后我们的红楼梦表df_hlm里虽然文字上的“第一卷”、“第二卷”、“第三卷”没有了,但是我们表格里的的每一行的序号也改变了。具体可以看下下面的例子:
# 举例:假设原索引存在缺失(如删除了第2行)
原始索引 | hlm_texts
--------------------
0 | "第一回..."
1 | "第二回..."
3 | "第四回..."新索引 | hlm_texts
--------------------
0 | "第一回..."
1 | "第二回..."
2 | "第四回..."
可以看到旧索引不连续了,所以需要更新排序:
(3)reset_index()
重置索引
生成新的连续整数索引(从0开始)
(4)drop=True
不要,不保留旧索引
hui_mask = df_hlm.hlm_texts.str.match(r'第.+?回')
df_hui = pd.DataFrame(df_hlm.hlm_texts[hui_mask].str.split(' ').tolist(),columns=['Huiname', 'Firstname', 'Secondname'])
先解读这一部分,后续的之后继续~