文章目录
一、实现核心功能
1、批量成图:一个excel文件,根据某属性值划分为若干子表,对每个子表绘制一张风玫瑰;
2、风玫瑰要素:风速、风向、风频
友情提醒:5.1.4、5.2.4部分为完整代码,其余部分为思路梳理。
二、Power by
1、柱状风玫瑰核心代码:览迹https://mp.weixin.qq.com/s/wCvfGC90UMFPK7j8gkQ4VQ
2、面积风玫瑰核心代码:梨树https://www.zhihu.com/question/43332611
3、GPT
感恩的心
三、成果展示
成果一:柱状风玫瑰
成果二:面积风玫瑰
四、excel数据预览
数据包括[datetime]、[WD]、[WS],及划分子表所需的属性,如本文根据[month]划分子表。
datetime | WD | WS | month |
---|---|---|---|
2024-01-01 00:00 | 254.5 | 0.7 | 1 |
…… | …… | …… | …… |
2024-02-01 00:00 | 212 | 0.6 | 2 |
…… | …… | …… | …… |
2024-03-01 00:00 | 217.1 | 0.6 | 3 |
五、实现思路
5.1柱状风玫瑰
柱状风玫瑰图,是我在作业中优化后的流程,直接在Python中处理数据(划分暂时子表)紧接着出图。
5.1.1划分子表
利用pandas将excel根据某属性划分为若干子表(不输出)。
import pandas as pd
# 读取文件
data=pd.read_excel(r'路径/文件名.xlsx',parse_dates=['datetime'])
# 定义划分子表的属性值(划分依据)
group_column = "month"
# 用groupby实现划分
sub_data=data.groupby(group_column) # 本行代码不出现在最终代码中,仅用来梳理思路
5.1.2各个子表绘制风玫瑰(批处理-分解1)
- 核心是利用for循环进行批处理;
- 利用windrose、matplotlib绘制风玫瑰,numpy进行数据处理;
from windrose import WindroseAxes
import matplotlib.cm as cm
import numpy as np
for month, sub_data in data.groupby(group_column):
# 读取数据
wd = sub_data["WD"]
ws = sub_data["WS"]
# 绘制风玫瑰
ax = WindroseAxes.from_ax() # 定义坐标系
ax.bar(wd, ws, normed=True, opening=0.8, edgecolor='white',bins=np.arange(0, 7,1),cmap=cm.cool) # 设置柱参数(风速0-7,以1等距划分,应用中需根据所需调整)
ax.tick_params(axis='both', labelsize=20) # 设置轴参数
ax.legend(frameon=False,ncol=1,fontsize=14,bbox_to_anchor=(1.05,0.3)) # 设置图例参数
5.1.3系列图件保存至本地(批处理-分解2)
利用matplotlib的子库pyplot生成图片(.png),利用os保存至本地文件夹中。该部分将在for循环中应用。
from matplotlib import pyplot as plt
import os
# 定义输出路径
output_dir = os.path.join(r"输出路径/", "结果文件夹名称")
# 定义输出文件
save_path = os.path.join(output_dir, f"windrose_{month}.png")
# 图片属性设置
plt.savefig(save_path, dpi=300, bbox_inches='tight')
# 打印进度
print(f"已保存: {save_path}")
# 关闭
plt.close()
5.1.4完整代码
from windrose import WindroseAxes
from matplotlib import pyplot as plt
import matplotlib.cm as cm
import numpy as np
import pandas as pd
import os
# 读取文件、定义输出路径
data=pd.read_excel(r'E:/8/10_制图/风玫瑰/批量柱状.xlsx',parse_dates=['datetime'])
output_dir = os.path.join(r"E:/8/10_制图/风玫瑰/", "风玫瑰图柱状")
# 定义划分子表的属性值(划分依据)
group_column = "month"
# 批量处理
for month, sub_data in data.groupby(group_column):
# 读取数据
wd = sub_data["WD"]
ws = sub_data["WS"]
# 绘制风玫瑰
ax = WindroseAxes.from_ax()
ax.bar(wd, ws, normed=True, opening=0.8, edgecolor='white',bins=np.arange(0, 7,1),cmap=cm.cool)
ax.tick_params(axis='both', labelsize=20)
ax.legend(frameon=False,ncol=1,fontsize=14,bbox_to_anchor=(1.05,0.3))
# 保存图像
save_path = os.path.join(output_dir, f"windrose_{month}.png")
plt.savefig(save_path, dpi=300, bbox_inches='tight')
# 结束
print(f"已保存: {save_path}")
plt.close()
5.2面积风玫瑰
面积风玫瑰相比于柱状,做成得早,流程较繁琐,且思维逻辑不同。若柱状风玫瑰的思维逻辑是你所喜欢的,并且没有再使用新思路的打算,可以直接基于5.1中的基本框架,主要修改5.1.2中的代码即可。
面积风玫瑰流程是,在excel中处理完成数据后(形成若干sheet),再在Python中对若干sheet批量成图至本地。
首先,在形成本部分代码中,包含我的不成熟的思维,我喜欢这份笨拙,所以没有剔除它;
其次,该代码还包含PowerBy中我学习到的东西:(1)多个sheet的批处理思路(2)定义函数、工作空间的意识,提高可复用性及整洁性;(3)非pandas而是xlrd读取Excel数据;
所以我决定在本文中进行记录。
5.2.1 excel处理数据
在excel中,利用数据透视表,将excel数据根据[month]划分为12个sheet。
Python中行列以[0,0]为首。如,划分出的12个子表中,以第[4,1]、[4,2]为风速、风向首行。
5.2.2 定义函数
1、利用matplotlib、windrose,定义风玫瑰坐标系。
from matplotlib import pyplot as plt
from windrose import WindroseAxes
def new_axes():
fig = plt.figure(figsize=(4, 4), dpi=80, facecolor='w', edgecolor='w') # 定义图片对象
rect = [0, 0, 1, 1] # 定义坐标系位置及大小
ax = WindroseAxes(fig, rect, facecolor='w') # 定义风玫瑰坐标系对象
fig.add_axes(ax) # 图片对象显示风玫瑰坐标系
return ax
2、利用matplotlib、定义图例。
from matplotlib import pyplot as plt
def set_legend(ax):
l = ax.legend(shadow=False, bbox_to_anchor=[1, 0]) # 定义图例
plt.setp(l.get_texts(), fontsize=12) # 设置文本格式
5.2.3 批处理
xlrd读取excel文件,利用for循环,读取12个sheet中第i个sheet,
import xlrd
from matplotlib import pyplot as plt
import matplotlib.cm as cm
import os
# 12个sheet中都有数据,一次绘制多个风玫瑰图
for i in range(12):
# 读取文件
workspace=(r"路径/") # 定义工作空间
mybook=xlrd.open_workbook(workspace+r'文件名.xls') # 利用xlrd打开文件
mysheet=mybook.sheet_by_index(i) # 定义sheet
rows=mysheet.nrows # 获取数据行数
# 读取数据(跳过无数据的前5行)
ws = mysheet.col_values(1)[4:]
wd = mysheet.col_values(2)[4:]
sl=[0,0.2,0.5,1,3,5] # 风速重分类间断点
# 绘制风玫瑰图
ax = new_axes() # 调用定义的风玫瑰函数
ax.contourf(wd,ws,bins=sl,cmap=cm.cool) # 使用内置colormap进行色彩分割
ax.set_title(mysheet.name,fontsize=15,loc='right') # 设置标题
set_legend(ax) # 调用定义的图例
# 导出图片
output_dir = os.path.join(workspace, "结果文件夹名称") # 定义输出路径
save_path = os.path.join(output_dir, f"windrose_{mysheet.name}.png") # 定义输出文件
plt.savefig(save_path, dpi=300, bbox_inches='tight') # 设置图片格式
# 结束
print(f"已保存: {save_path}") # 打印进度
plt.close() # 关闭图像,释放内存
5.2.4完整代码
import xlrd
import matplotlib as mpl
from matplotlib import pyplot as plt
from windrose import WindroseAxes
import matplotlib.cm as cm
import os
# 显示中文
mpl.rcParams['font.sans-serif'] = ['SimHei']
# 定义风玫瑰坐标系
def new_axes():
fig = plt.figure(figsize=(4, 4), dpi=80, facecolor='w', edgecolor='w')
rect = [0, 0, 1, 1]
ax = WindroseAxes(fig, rect, facecolor='w')
fig.add_axes(ax)
return ax
# 定义图例
def set_legend(ax):
l = ax.legend(shadow=False, bbox_to_anchor=[1, 0])
plt.setp(l.get_texts(), fontsize=12)
#批处理
for i in range(12):
# 读取文件
workspace=(r"E:/8/10_制图/风玫瑰/")
mybook=xlrd.open_workbook(workspace+r'批量.xls')#打开文件
mysheet=mybook.sheet_by_index(i)
rows=mysheet.nrows
# 读取数据
ws = mysheet.col_values(1)[4:]
wd = mysheet.col_values(2)[4:]
# 设置风速间断点(重分类-根据所需调整)
sl=[0,0.2,0.5,1,3,5]
# 图件特色化设置
ax = new_axes()
ax.contourf(wd,ws,bins=sl,cmap=cm.cool)
ax.set_title(mysheet.name+"月风玫瑰图",fontsize=15,loc='center')
set_legend(ax)
# 导出图片
output_dir = os.path.join(workspace, "风玫瑰图面积1")
save_path = os.path.join(output_dir, f"windrose_{mysheet.name}.png")
plt.savefig(save_path, dpi=300, bbox_inches='tight')
# 结束
print(f"已保存: {save_path}")
plt.close()
六、小结
没什么好结的,只是要个仪式感,Over。