900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > python详解绘制风玫瑰图

python详解绘制风玫瑰图

时间:2023-10-15 11:31:41

相关推荐

python详解绘制风玫瑰图

绘制风玫瑰图

# 导入包import numpy as npimport pandas as pdimport matplotlib.pyplot as plt#-------设置支持中文----------------------#import matplotlib as mplmpl.rcParams['font.sans-serif'] = ['SimHei'] #设置简黑字体mpl.rcParams['axes.unicode_minus'] = False#-------自定义坐标轴刻度格式----------------#from matplotlib.ticker import FuncFormatter

创建数据集:

np.random.seed(0)data = pd.DataFrame(np.random.randint(20, 300, (4, 16)), index=['0~0.2', '0.3~1.5', '1.6~3.3', '3.4~5.4'],columns='N NNE NE ENE E ESE SE SSE S SSW SW WSW W WNW NW NNW'.split())data #风速选择了4段,每列数据表示各方向风速的频数统计值

绘制频数风速玫瑰图:

N = 16 # 风速分布为16个方向theta = np.linspace(0, 2*np.pi, N, endpoint=False) # 获取16个方向的角度值width = np.pi / N # 绘制扇型的宽度,可以自行调整labels = list(data.columns) # 自定义坐标标签为 N , NSN, ……# 开始绘图plt.figure(figsize=(8,8))ax = plt.subplot(111, projection='polar')for idx in data.index:# 每一行绘制一个扇形radii = data.loc[idx] # 每一行数据ax.bar(theta, radii, width=width, bottom=0.0, label=idx, tick_label=labels)plt.title('风玫瑰图示意图')plt.legend(loc=4, bbox_to_anchor=(1.15, -0.07)) # 将label显示出来, 并调整位置plt.show()

已经可以初步满足需求了,不过我们发现N位置差了90°,而且为了满足‘上北下南左西右东’的习惯,需要逆时针方向绘制。所以做两个修改:

N = 16 # 风速分布为16个方向theta = np.linspace(0, 2*np.pi, N, endpoint=False) # 获取16个方向的角度值width = np.pi / N # 绘制扇型的宽度,可以自行调整labels = list(data.columns) # 自定义坐标标签为 N , NSN, ……# 开始绘图plt.figure(figsize=(8,8))ax = plt.subplot(111, projection='polar')for idx in data.index:# 每一行绘制一个扇形radii = data.loc[idx] # 每一行数据ax.bar(theta, radii, width=width, bottom=0.0, label=idx, tick_label=labels)#------------------------------------#ax.set_theta_zero_location('N') #设置零度方向北ax.set_theta_direction(-1) # 逆时针方向绘图plt.title('风玫瑰图示意图')plt.legend(loc=4, bbox_to_anchor=(1.15, -0.07)) # 将label显示出来, 并调整位置plt.show()

这样基本满足我们的需求了,但是有的时候我们需要绘制百分比玫瑰图,下面我们讨论如何制作百分比风玫瑰图:

数据转化为百分比

_sum = data.apply(np.sum)data = data / _sumdata

数据转化成功,我们绘制图片唯一要修改的就是yaxis(本质是bar图,我们仔细观察上面的图不难发现原因)刻度的表达,将其转化为百分比:

N = 16 # 风速分布为16个方向theta = np.linspace(0, 2*np.pi, N, endpoint=False) # 获取16个方向的角度值width = np.pi / N # 绘制扇型的宽度,可以自行调整labels = list(data.columns) # 自定义坐标标签为 N , NSN, ……# 开始绘图plt.figure(figsize=(8,8))ax = plt.subplot(111, projection='polar')for idx in data.index:# 每一行绘制一个扇形radii = data.loc[idx] # 每一行数据ax.bar(theta, radii, width=width, bottom=0.0, label=idx, tick_label=labels)#------------------------------------#ax.set_theta_zero_location('N') #设置零度方向北ax.set_theta_direction(-1) # 逆时针方向绘图#--------自定义yaxis的刻度格式-----------#plt.gca().yaxis.set_major_formatter(FuncFormatter(lambda s, position: '{:.0f}%'.format(100*s)))plt.title('风玫瑰图示意图')plt.legend(loc=4, bbox_to_anchor=(1.15, -0.07)) # 将label显示出来, 并调整位置plt.show()

数据遮挡处理

细心的同学可能已经发现,由于数据绘制是按行来绘制的,那么如果先绘制的数据值比较小的话,会被后面的数据遮挡。以风频数据为例,处理思路如下:

按列绘制数据(先处理同一风向的数据)每列中先将数值较大的绘制出来-解决遮挡的问题最后一列处理下图例

此外加入了自定义颜色(根据风向分类条数自定义

完整代码如下

# 导入包import numpy as npimport pandas as pdimport matplotlib.pyplot as plt#-------设置支持中文----------------------#import matplotlib as mplmpl.rcParams['font.sans-serif'] = ['PingFang HK'] #设置字体mpl.rcParams['axes.unicode_minus'] = Falsedef plot_bar(ax, theta, values, width, colors):plt_data = [(i, values[i]) for i in range(len(values))]for idx, data in sorted(plt_data, key=lambda s: s[-1], reverse=True):ax.bar(theta, data, width, color=colors[idx])def lengend_plot(ax, theta, values, width, colors):plt_data = [(i, values[i]) for i in range(len(values))]for idx, data in sorted(plt_data, key=lambda s: s[-1], reverse=True):p = ax.bar(theta, data, width, color=colors[idx])yield (idx, p)if __name__ == "__main__":# 生成数据np.random.seed(0)data = pd.DataFrame(np.random.randint(20, 300, (4, 8)),index=['0~0.2', '0.3~1.5', '1.6~3.3', '3.4~5.4'],columns='N NE E SE S SW W NW'.split())N = data.shape[-1] # 由数据模板获取风向类别theta = np.linspace(0, 2 * np.pi, N, endpoint=False) # 获取16个方向的角度值width = np.pi / N # 绘制扇型的宽度,可以自行调整labels = data.columns.to_list() # 获取标签colors = ['#060080', '#00D5FF', '#FFE600','#800000'] # 自定义颜色,颜色的尺寸必须与数据的分类条数一致# 开始绘图plt.figure(figsize=(10, 8))ax = plt.subplot(111, projection='polar')for i in range(N - 1):values = data.iloc[:, i].to_list()plot_bar(ax, theta[i], values, width, colors)handles = lengend_plot(ax, theta[N - 1], data.iloc[:, N - 1], width,colors)handles = [p for idx, p in sorted(handles, key=lambda s: s[0])]ax.set_xticks(theta) # 自定义坐标轴标签ax.set_xticklabels(labels)ax.set_theta_zero_location('N') #设置零度方向北ax.set_theta_direction(-1) # 逆时针方向绘图plt.title('风玫瑰图示意图')plt.legend(handles, data.index, loc=4,bbox_to_anchor=(1.15, -0.07)) # 将label显示出来, 并调整位置plt.show()

绘制结果

如果喜欢的话欢迎👍点赞评论,⭐️github地址欢迎star、flow!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。