数据可视化的题目
需求是说,在一个小说的 txt文件中,查询下面 characers 中,这些 人名 出现次数,并保存在 data.csv 中
然后,利用收集到的信息 做出 折线图,用 出场最多的5个人的次数 做出饼图。。
搜索数据,并记录
首先呢,需要去文本中 查询字段出现次数。
查询次数的话,就是用 with open("赘婿.txt","r",encoding="utf-8"),打开 赘婿.txt文件,后面的 r 参数代表 访问形式是 读取,最后的 encoding是说 编码方式为 utf-8。
玩过别的语言的单机游戏的话,相信都碰到过需要改文件编码方式(虽然我忘了在哪碰到过)。中文的编码 貌似有很多种,utf-8 就是一种。
打开了文件以后呢,我们需要去读取内容对吧?将所有内容 赋值给 content,然后我们 利用 for 的特性,一行一行的方式读取(其实,把文本框拉长会发现,每一段其实算一行,而人物名字明显不会说 从中间截断)。
使用 .strip(),将 每一行中 前后的空格删去(其实在这里 删不删没啥区别)
后面 如果是空行,则直接跳过。
最后就是 对比名字是否出现啦!我的思路是,遍历到每一个字的时候,让这个字和后面一个 或 两个 ,一起与 字典中 人物名字对比。如果匹配 则记录+1。(搜索会很慢,python还不太熟悉,不太会改 哈哈哈)
上面这些结束后,就完成了 人名出现次数的记录。这时候 characers 中 保存着所有的信息。
characers = {'苏檀儿': 0, '宁毅': 0, '刘西瓜': 0, '秦嗣源': 0, '陆红提': 0, '苏仲堪': 0, '苏文兴': 0, '苏伯庸': 0, '耿护院': 0, '元锦儿': 0, '宋宪': 0,
'陈凡': 0}
with open("赘婿.txt", "r", encoding="utf-8") as fr:
content = fr.read()
# 依次迭代所有⾏
for line in content:
# 去除空格
line = line.strip()
# 如果是空⾏,则跳过
if len(line) == 0:
continue
# 统计每⼀字出现的个数
for x in range(0, len(line)):
for y in characers:
if line[x:x + 2] == y[0] or line[x:x + 3] == y[0]:
characers[y] += 1
导出数据至 data.csv
第二步,我们需要去将 characer 中的数据 导入到 csv文件中。
还是一样,首先先用 with open("data.csv", "w") 以写入形式打开文件,并且用 csv_file 代替访问。
使用csv中自带函数 csv.DictWriter(目标文件,列名) ,并且使用 .writeheader(),将其写入。
后面就是将 characer 变为列表,然后用 for 和 csv_writer.writerow() 将其中 人名和次数 分行写在 “人名”和“次数”下面。
with open("data.csv", "w") as csv_file:
csv_writer = csv.DictWriter(csv_file, fieldnames=['人名', '次数'])
csv_writer.writeheader()
key = list(characers.keys())
value = list(characers.values())
for i in range(len(key)):
dic = { # 字典类型
'人名': key[i],
'次数': value[i]
}
csv_writer.writerow(dic)
折线图
第三步就是 读取 data.csv 中数据,将其作成折线图
为了避免后续 饼图中 使用 characers 的数据(不想每次都去重新算 出现了多少次),声明 characters 字典,在下方循环的时候 将data.csv数据 copy
和前面一样,首先打开文件,将其指针赋值给f,然后读取文件,将其中的值 赋给 reader。
然后读取第一行,将其值 赋给 header_row(算是列名)
新建两个列表,分别保存 csv中 人名 和 次数。这里做个条件判断,如果说 这一行是空行,就直接跳过。(不知道为啥,我打开的时候发现,导入一个数据,他就空一行)
这个 for 做完,就有了所有数据。
利用 plt.plot(横坐标,纵坐标,color,) 定义折线图的 横纵坐标,线的颜色
plt.title("标题",fontsize(字体大小))
plt.xlabel('横坐标显示的文字',fontsize(字体大小))
同理 plt.ylabel 设置纵坐标显示的文字。
最后 plt.show() 即可显示出 图
characters = {}
with open("./data.csv") as f:
reader = csv.reader(f)
header_row = next(reader)
names, times = [], []
for row in reader:
if len(row)>1:
name = row[0]
time = int(row[1])
names.append(name)
times.append(time)
plt.plot(names, times, c='red', alpha=0.3)
# plt.fill_between(dates, highs, lows, facecolor='blue', alpha=0.05)
title = "人物出现次数折线图 "
plt.title(title, fontsize=24)
plt.xlabel('name', fontsize=16)
plt.ylabel('times', fontsize=16)
plt.show()
饼图
和前面一样,不过因为说,需要数量上为 前五的人,所以需要对数据进行一次排序。
这边的思路是,利用前面新建的 character 字典的数据,排序成 列表形式,采用倒序。
最后把 人名和次数 分别放在 names 和 indexs中
后面就是 画图 .pie(数据,数据对应的标签,数据形式)
n = 5
L = sorted(characers.items(), key=lambda item: item[1], reverse=True)
L = L[:n]
names = []
indexs = []
for name, index in L:
names.append(name)
indexs.append(index)
fig = plt.figure()
plt.pie(indexs, labels=names, autopct='%1.2f%%') # 画饼图(数据,数据对应的标签,百分数保留两位小数点)
plt.title("出场最多的五个角色 ")
plt.show()
源代码
import csv
from matplotlib import pyplot as plt
import pandas as pd
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
characers = {'苏檀儿': 0, '宁毅': 0, '刘西瓜': 0, '秦嗣源': 0, '陆红提': 0, '苏仲堪': 0, '苏文兴': 0, '苏伯庸': 0, '耿护院': 0, '元锦儿': 0, '宋宪': 0,
'陈凡': 0}
with open("赘婿.txt", "r", encoding="utf-8") as fr:
content = fr.read()
# 依次迭代所有⾏
for line in content:
# 去除空格
line = line.strip()
# 如果是空⾏,则跳过
if len(line) == 0:
continue
# 统计每⼀字出现的个数
for x in range(0, len(line)):
for y in characers:
if line[x:x + 2] == y[0] or line[x:x + 3] == y[0]:
characers[y] += 1
with open("data.csv", "w") as csv_file:
csv_writer = csv.DictWriter(csv_file, fieldnames=['人名', '次数'])
csv_writer.writeheader()
key = list(characers.keys())
value = list(characers.values())
for i in range(len(key)):
dic = { # 字典类型
'人名': key[i],
'次数': value[i]
}
csv_writer.writerow(dic)
characters = {}
with open("./data.csv") as f:
reader = csv.reader(f)
header_row = next(reader)
names, times = [], []
for row in reader:
if len(row) > 1:
name = row[0]
time = int(row[1])
names.append(name)
times.append(time)
characters[name] = time
plt.plot(names, times, c='red', alpha=0.3)
# plt.fill_between(dates, highs, lows, facecolor='blue', alpha=0.05)
title = "人物出现次数折线图 "
plt.title(title, fontsize=24)
plt.xlabel('name', fontsize=16)
plt.ylabel('times', fontsize=16)
plt.show()
# title += '\nSitka, AK and Death Valley, CA'
# fig.autofmt_xdate() # 绘制斜的日期标签
# plt.tick_params(axis='both', labelsize=16)
# plt.ylim(10, 120) # 设置y轴范围
n = 5
L = sorted(characters.items(), key=lambda item: item[1], reverse=True)
L = L[:n]
names = []
indexs = []
for name, index in L:
names.append(name)
indexs.append(index)
fig = plt.figure()
plt.pie(indexs, labels=names, autopct='%1.2f%%') # 画饼图(数据,数据对应的标签,百分数保留两位小数点)
plt.title("出场最多的五个角色 ")
plt.show()