python实验数据预处理案例_Python数据分析小案例——红楼梦文本分析(一) 文本预处理...

本文开始介绍一个简单的数据分析案例,分析红楼梦文本,本文主要内容是将红楼梦文本按照章节获取每一回的标题,字数,段落数并保存到csv中方便后续数据分析

红楼梦小说文本可以在这里下载

链接:https://pan.baidu.com/s/1WEmunBN_Wo75EZd1cK6_lA

提取码:3xco

接下来直接上代码

import pandas as pd

import numpy as np

with open("./hlm/red.txt",encoding="utf-8") as f:

content = f.readlines()

content = pd.DataFrame(content) #将行转为df,这个df只有一列

content.columns = ["content"] #取列名为content,以防content[0]会有歧义,不知道是表示第一列还是第一行

print(content)

#查看是否有为空的行

print(np.sum(content.isnull()))

#删除 第x卷 这样的行

has_juan = content["content"].str.contains(r"^第.+?卷") #返回 [True,False,....,False]

# print(content[has_juan])

index_has_juan = has_juan.index[has_juan.values==True] #或者has_juan[has_juan==True].index

# print(content.drop(index_has_juan))

content = content.drop(index_has_juan)

content = content.reset_index(drop=True) #重新设定index

#或者这样做也可以

has_juan = content["content"].str.contains(r"^第.+?卷")

content = content[~has_juan].reset_index(drop=True) #content[has_juan] 就是有卷的行,~取反 是没有第x卷的行

print(content)

content.to_csv("./hlm_cont.csv",index=False)

#获取每一回的标题

has_hui = content["content"].str.match(r"^第.+回") #match和contains都一样

cont_with_hui = content[has_hui]["content"].str.strip("\r\n").str.split(" ").reset_index(drop=True) #获取回的行并且将里面的内容按照空格分开,这里返回的是一个Series

print(cont_with_hui)

df_hui = pd.DataFrame(list(cont_with_hui),columns=["chapterNum","leftName","rightName"]) #这里必须将cont_with_hui从series转为list,否则得到的是一个空df

print(df_hui)

df_hui["fullName"] = df_hui['leftName']+pd.Series([" " for i in range(len(df_hui))])+df_hui['rightName']

print(df_hui)

#获取每一回的段落数和字数

#段落数 = 每回最后一段的行号-回标题所在的行号

df_hui['parag_start'] = has_hui[has_hui==True].index #回标题所在行号

parag_end = df_hui['parag_start'][1:len(df_hui['parag_start'])]-1 #每回最后一行行号

parag_end = parag_end.reset_index(drop=True) #此时parag_end只有119个元素,还缺最后一回的最后一段的行号

parag_end[len(parag_end)] = content.index[-1]

df_hui['parag_end'] = parag_end

df_hui['parag_num'] = df_hui['parag_end'] - df_hui['parag_start'] #段落数

#每回的字数 = 每回的段落所在的行的内容的长度求和(文字内容不包括\r\n,回标题字数不算在内)

str_len = content['content'].apply(lambda x:len(x.strip("\r\n").replace(" ","")))

str_len_hui = pd.Series(np.arange(len(df_hui))) #这里str_len_hui不能生成一个空Series,否则下面str_len_hui[i]=xxx会报错

# print(str_len_hui)

for i in range(len(df_hui)):

#获取每回的开始段和结束段的index

start = df_hui['parag_start'][i]+1

end = df_hui['parag_end'][i]

#获取每回所在的行

hang_each_hui = str_len[start:(end+1)]

str_len_hui[i] = hang_each_hui.sum() #对每回对应的所有行的字数求合,就是每回的字数

print(str_len_hui)

df_hui['str_len']= str_len_hui

#将红楼梦回的数据存为csv

df_hui.to_csv("./hlm_chapter_info.csv",index=False)

得到的csv内容如下:

红楼梦章节文本处理

得到了每一章的字数和段落数之后,可以根据绘出字数和段落数的散点图和折线图,代码实现如下:

# 根据红楼梦每一回的数据做每回段落数和字数的散点图,并在每个点上标记是第几回

import matplotlib.pyplot as plt

import pandas as pd

import numpy as np

plt.rcParams['font.sans-serif']=['SimHei'] #正常显示中文

plt.rcParams['axes.unicode_minus'] = False #正常显示负号

df_hui = pd.read_csv("./hlm_chapter_info.csv")

print(df_hui)

fig = plt.figure(figsize=(16,16))

fig.suptitle("《红楼梦》120回") #四个图的总标题,plt.title()是设置子标题

plt.subplot(221)

plt.scatter(df_hui['parag_num'],df_hui['str_len'])

plt.xlabel("每回段落数")

plt.ylabel("每回字数")

for i in range(len(df_hui)):

plt.text(df_hui['parag_num'][i],df_hui['str_len'][i],df_hui['chapterNum'][i],size=7) #给每个点做上文字说明,前两参是文字说明的位置,x,y;第三参是文字说明的内容;size是字体大小

plt.subplot(222)

plt.scatter(df_hui['parag_num'],df_hui['str_len'])

plt.xlabel("每回段落数")

plt.ylabel("每回字数")

for i in range(len(df_hui)):

plt.text(df_hui['parag_num'][i]+1,df_hui['str_len'][i],i+1)

#绘制点线图,横坐标是章节数,纵坐标是章节字数和章节段落数

plt.subplot(223)

plt.plot(df_hui.index+1,df_hui['parag_num'],"ro-")

plt.hlines(np.mean(df_hui['parag_num']),-5,125) #画一条水平线,显示段落数的平均值

plt.xlim((-5,125)) #限制x轴视图范围

plt.xlabel("章节")

plt.ylabel("章节段落数")

plt.subplot(224)

plt.plot(df_hui.index+1,df_hui['str_len'],"ro-") #r红色,o控制点的样式,-控制线的样式

plt.hlines(np.mean(df_hui['str_len']),-5,125)

plt.xlim((-5,125))

plt.xlabel("章节")

plt.ylabel("章节字数")

plt.savefig("hlm1.png")

plt.show()

得到的图像如下图所示(图片较大,可以点击图片查看放大的图片):

红楼梦章节字数和段落数散点图和折线图

你可能感兴趣的:(python实验数据预处理案例)