Python案例:批量绘制风玫瑰图

一、实现核心功能

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]划分子表。

datetimeWDWSmonth
2024-01-01 00:00254.50.71
……………………
2024-02-01 00:002120.62
……………………
2024-03-01 00:00217.10.63

五、实现思路

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。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值