python大作业进阶——绘制滚动图
python绘制滚动图
上面就是效果图(结果为MP4视频)
代码展示:
1、加载库
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei']
2、读取文件
df = pd.read_csv('Province_GDP.csv', index_col=0 ,encoding='utf-8')
data = df.to_dict(orient='dict')
3、设定每个省市所用的颜色
# 推荐一个找颜色的网址https://html-color-codes.info/chinese/
colors = {'北京市': '#FFA500',
'天津市': '#1E90FF',
'河北省': '#FF0000',
'山西省': '#FF1493',
'内蒙古自治区': '#127436',
'辽宁省': '#FAA460',
'吉林省': '#9400D3',
'黑龙江省': '#8B0000',
'上海市': '#C0C0C0',
'江苏省': '#87CEEB',
'浙江省': '#8FBC8F',
'安徽省': '#FFFF00',
'福建省': '#C71585',
'江西省': '#800080',
'山东省': '#FF8C00',
'河南省': '#E60000',
'湖北省': '#BDB76B',
'湖南省': '#FFA500',
'广东省': '#008000',
'广西壮族自治区': '#000000',
'海南省': '#E5EE2E',
'重庆市': '#777777',
'四川省': '#0000FF',
'贵州省': '#CD5C5C',
'云南省': '#20B2AA',
'西藏自治区': '#E6D933',
'陕西省': '#00BFFF',
'甘肃省': '#191970',
'青海省': '#D1F417',
'宁夏回族自治区': '#FF69B4',
'新疆维吾尔族自治区': '#75D6F2'}
4、将时间段单独抽出作为一个列表,另外生成一个存放数据的列表,且对应每个时间段的各省的GDP由大到小进行排序
date = []
number_sort = []
for key, value in data.items():
date.append(key)
number_sort.append(sorted(value.items(), key=lambda d:d[1], reverse = True))
5、设计算法,生成视频每一帧所需要的图片
以下为主程序,每一步均有注释,不做详细分布说明
count = 0 #
for i in range(len(number_sort)):
provinces_now = {} # 本年的排序
provinces_next = {} # 后一年的排序
# 由于最后一组数据与前几组数据处理不同,先处理前几组数据
if i !=len(number_sort)-1:
for (province,gdp) in number_sort[i]:
provinces_now[province] = gdp # 将本年的数据写入字典
for (province,gdp) in number_sort[i + 1]:
provinces_next[province] = gdp # 将下一年的数据写入字典
provinces_rank_now = list(provinces_now.keys())
provinces_rank_next = list(provinces_next.keys())
#设置0矩阵用于位次的记录
provinces_rank_change = np.zeros((31))
#讲位次的改变记录在矩阵中
for j in range(31):
provinces_rank_change[j] = provinces_rank_next.index(provinces_rank_now[j]) - j
#由于之后每一年的数据以30张图片输出,所以这里÷30来分配每一帧的数据变化
provinces_rank_per_change = list(provinces_rank_change / 30)
#将排序好的省份以及当前顺序写入字典中
provinces_rank_record = {}
for j in range(31):
provinces_rank_record[provinces_rank_now[j]] = j + 1
#设置0矩阵用于差值的计算,也为后续的数据变化做准备
provinces_data_change = np.zeros((31))
for j in range(31):
provinces_data_change[j] = provinces_next[provinces_rank_now[j]] - provinces_now[provinces_rank_now[j]]
#由于之后每一年的数据以30张图片输出,所以这里÷30来分配每一帧的数据变化
provinces_data_per_change = list(provinces_data_change / 30)
#由于数据较多,模拟靠前的一半输出
for k in range(30):
# 先准备一些格式较多的数据以免后续使用
# 开一个ax的绘图面板
fig, ax = plt.subplots(figsize=(19.2,10.8), dpi=100)
#省份名字和排行
provinces_name_rank = sorted(provinces_rank_record.items(),key=lambda x:x[1],reverse=False)[:15]
#省份名字和GDP数据
provinces_name_data = sorted(provinces_now.items(),key=lambda x:x[1],reverse=True)[:15]
#省份排序
provinces = [w[0] for w in provinces_name_rank]
#顺序 其实就是1-15的排序,也可range(1,16)
provinces_r = [w[1] for w in provinces_name_rank]
#数据 按顺序排序的数据(GDP值)
provinces_d = [provinces_now[w] for w in provinces]
#省份所对应的颜色
color = []
for province in provinces:
color.append(colors[province])
# 以横向的柱状图展现,并设置参数
# matplotlib绘制图表参考https://blog.csdn.net/weixin_40683253/article/details/87641416
b = ax.barh(provinces_r,provinces_d,0.5, # x轴,y轴,柱条宽度
edgecolor = 'white', # 边框颜色
color = color, # 填充颜色
tick_label = provinces, # 图例
alpha = 0.7) #透明度
# pyplot.text的用法参考https://blog.csdn.net/The_Time_Runner/article/details/89927708
# ha、va的用法参考https://blog.csdn.net/qq_39131592/article/details/79056255
for rect in b:
w = rect.get_width()
#print(w)
#print(rect.get_y())
#print(rect.get_y() + rect.get_height()/2)
ax.text(w + 1500, rect.get_y() + rect.get_height()/2,
'%d'%w, # 注释内容
ha='left',# 垂直对齐方式
va='center')# 水平对齐方式
# 隐藏上边和右边的坐标轴
# 参考https://blog.csdn.net/qq_41011336/article/details/83015986
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
# 添加对应的年份
ax.text( 7 * b[0].get_width()/10, 12 ,date[i],fontsize=28)
ax.text( 6 * b[0].get_width()/10, 11 ,'处于领跑状态的省份是:{}'.format(provinces[0]),fontsize=27)
# 绘制整个图像的标题
plt.title('全国各省2010-2018年GDP变化', fontsize=29)
# 保存图片,文件名自己修改
plt.savefig('picture/{} {}.png'.format('%02d'%i, '%02d'%k))
# 关闭plt
plt.close('all')
#数据更新迭代,加上已经准备好的差值
for t in range(31):
provinces_rank_record[provinces_rank_now[t]] += provinces_rank_per_change[t]
provinces_now[provinces_rank_now[t]] += provinces_data_per_change[t]
count+=1
print('已完成{:.2%}'.format(count/243))
else:
# 几乎复制上一段代码
for k in range(3):
#由于是最后一组数据,没有滚动展示,只做两张图片处理,其余与上面相同
for (province,gdp) in number_sort[i]:
provinces_now[province] = gdp
fig, ax = plt.subplots(figsize=(19.2,10.8), dpi=100)
provinces_fin_rank = sorted(provinces_rank_record.items(),key=lambda x:x[1],reverse=False)[:15]
provinces = [w[0] for w in provinces_fin_rank]
provinces_r = [w[1] for w in provinces_fin_rank]
provinces_d = [provinces_now[w] for w in provinces]
color = []
for province in provinces:
color.append(colors[province])
b = ax.barh(provinces_r,provinces_d,0.5,edgecolor = 'white',color = color, tick_label = provinces, alpha = 0.7)
for rect in b:
w = rect.get_width()
ax.text(w + 1500, rect.get_y() + rect.get_height()/2, '%d'%w, ha='left', va='center')
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
ax.text( 7 * b[0].get_width()/10, 12 ,date[i],fontsize=28)
ax.text( 6 * b[0].get_width()/10, 11 ,'处于领跑状态的省份是:{}'.format(provinces[0]),fontsize=27)
ax.text( 7 * b[0].get_width()/10, 10 ,'谢谢观看',fontsize=28)
plt.title('全国各省2010-2018年GDP变化', fontsize=29)
plt.savefig('picture/{} {}.png'.format('%02d'%i, '%02d'%k))
plt.close('all')
count+=1
print('已完成{:.2%}'.format(count/243))
print('图片保存完成,请进行后续程序,感谢您耐心的等待。')
6、利用opencv将图片合成视频
# 将图片合成视频用到opencv,参考https://blog.csdn.net/qq_33287871/article/details/100065144
import cv2
import os
# 帧率即每秒钟展示多少张图片
fps = 30
# 图片大小信息
size = (1920, 1080)
#音视频封装格式编码格式,参考https://blog.csdn.net/ubuntulover/article/details/6219056
fourcc = cv2.VideoWriter_fourcc('m', 'p', '4', 'v')
videowriter = cv2.VideoWriter("province.mp4",fourcc, fps, size)
# 文件地址
path = r'C:\Users\52287\picture\\'
# 合成视频
for i in os.listdir(path):
img = cv2.imread(path + i)
videowriter.write(img)
videowriter.release()
代码中存在的路径自己修改,源码地址
https://pan.baidu.com/s/1uEcc4lLa0ZFVB_bNJEmNIg
提取码:bomj