风玫瑰(Wind Rose)作图及分析

风玫瑰图在风力发电、气象、城市规划乃至保险等领域有着广泛应用,本文简单介绍了风玫瑰图的作图过程和简要的可视化与分析思路。

风玫瑰图

风玫瑰图(wind rose plot)作为一种气象科学的专用图表,是用来定量分析气象要素中风的一种工具。同时,风玫瑰图作为风电场建设前期必不可少的步骤——“风能资源评估”的主要工具,也越来越受到能源部门的建设者和规划者的重视。在风玫瑰图的极坐标系上,每一部分的长度表示该风向出现的频率,最长的部分表示该风向出现的频率最高。风玫瑰图通常分16个方向,也有的再细分为32个方向。因图形似玫瑰花朵,故此得名。

具体而言,风玫瑰图可分为风向玫瑰图和风速玫瑰图,用来简单描述某一地区风向风速的分布。风玫瑰图采用极坐标系来呈现数据,极坐标系下从外向内的方向代表风的方向,某条半径的长度,也就代表了该风向在所有记录中的比例(百分比、频次)。如果半径长度代表的是平均风速的大小,此时风玫瑰图就为风速玫瑰图。

进一步地,风玫瑰图可以同时展现风速和风向两类信息。在风向玫瑰图的基础上,在每一个方向上,如果将半径划分按照不同风速出现的比例加以标注(类似直方图的形式),风速的统计信息就得以呈现出来。

显然,风玫瑰图反映了一个地方的风力特点,“风玫瑰”中最大的花瓣就是当地的主导风向,因此在气候计算、城市规划、风力发电等方面有广泛的应用。同时,风玫瑰图的制作也并不复杂:

  1. 采集实时风向风速数据(例如,频率5分钟);
  2. 将采集的风速风向数据统计到各个方向上;
  3. 进行数据的清洗和规范化,绘制极坐标直方图。

基于windrose的风玫瑰图

导入数据

在Python中,我们将采用windrose库(https://github.com/python-windrose/windrose )来绘制玫瑰图。国内的风速的高频数据没有找到,这里采用美国国家可再生能源实验室(The National Renewable Energy Laboratory, https://www.nrel.gov/ )提供的数据作为示例。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import matplotlib.pyplot as plt
import matplotlib.cm as cm
from matplotlib.pylab import rcParams

import cartopy.crs as ccrs

import plotly.graph_objs as go
import plotly.offline as py_offline
import plotly.plotly as py

from plotnine.ggplot import *
from plotnine.geoms import *
from plotnine.coords import *
from plotnine.labels import *
from plotnine.data import *
from plotnine.facets import *
from plotnine.scales import *
from plotnine import qplot

import pandas as pd
import numpy as np
import os

py_offline.init_notebook_mode(connected=True)
rcParams['figure.figsize'] = [15, 12]
1
2
stn = pd.read_csv(os.getcwd()+'/data/47084-2007.csv', nrows=3, header=None)
stn
0 1 2 3 4 5
0 SiteID 47084.000000 Site Timezone -7.0 Data Timezone 0.0
1 Longitude -106.101776 NaN NaN NaN NaN
2 Latitude 39.378006 NaN NaN NaN NaN

从数据的表头信息可以看出,气象站点位于北纬39.378度,西经106.102度,从地图上可以看出大致位于美国科罗拉多州落基山脉内,距离落基山脉最高峰埃尔伯特峰几十公里,利用Cartopy可以很容易地标出站点位置。

(褐色长条状的就是落基山脉咯)

RockyMountainsLocatorMap

1
2
3
4
5
6
7
8
9
fig = plt.figure(facecolor='grey',figsize=(15, 12))
ax = plt.axes(projection=ccrs.PlateCarree())
ax.stock_img()
ax.plot([stn.iloc[1,1]],[stn.iloc[2,1]],
color='blue', marker='o', transform=ccrs.PlateCarree())

plt.text(stn.iloc[1,1] + 30, stn.iloc[2,1] - 10, 'Station Location',
horizontalalignment='right', fontsize=16,
transform=ccrs.Geodetic())
Text(-76.101776, 29.378006, 'Station Location')

output_5_1

stn_on_earth

可以看到数据的采样频率为5分钟,测量的风速为地表100米高度的风,除风速和方向信息以外,还有风力资源、温度、气压等信息。根据风速和方向,可以进一步得到风速在水平和垂直方向上的分量,u-wind、v-wind分别为水平、垂直方向的风速分量。南北水平方向,东西垂直方向。按上北、下南、左西、右东建立坐标轴,正北为0°,顺时针风向为正:

uwind=WS×sin(WD/180×π){u-wind}={WS}\times \sin{({WD}/180\times \pi)}

vwind=WS×cos(WD/180×π){v-wind}={WS}\times \cos{({WD}/180\times \pi)}

其中,WS-风速,WD-风向。

1
2
3
4
5
6
7
df = pd.read_csv(os.getcwd()+'/data/47084-2007.csv', header=3)
df['Date'] = pd.to_datetime(df[['Year', 'Month', 'Day', 'Hour', 'Minute']])
df = df.rename(columns={'wind speed at 100m (m/s)': 'windspeed',
'wind direction at 100m (deg)': 'direction'})
df['u-wind'] = df['windspeed'] * np.sin(df['direction'] * np.pi / 180.0)
df['v-wind'] = df['windspeed'] * np.cos(df['direction'] * np.pi / 180.0)
df.head()

风力数据可视化

首先看一下,风速和风向在一年之内的变化情况、风向的分布(风速的见后)以及风速与风向之间的关系。可以明显观察到以下现象:

  1. 夏季的风速(6月底~8月底)明显小于其他季节;
  2. 风向以西风为主,尤以西微偏北居多,夏季西风的比例明显小于其他季节;
  3. 极端强风主要来自于西风方向。
1
2
3
4
(ggplot(data=df) +
aes(x='Date',y='windspeed', color='windspeed') +
geom_line()
)

output_10_0

1
2
3
4
(ggplot(data=df) +
aes(x='Date',y='direction', color='direction') +
geom_point()
)

output_11_0

1
2
3
4
(ggplot(data=df) +
aes(x='direction') +
geom_histogram()
)
C:\ProgramData\Anaconda3\lib\site-packages\plotnine\stats\stat_bin.py:93: UserWarning:

'stat_bin()' using 'bins = 134'. Pick better value with 'binwidth'.

output_12_1

1
2
3
4
5
6
from windrose import WindroseAxes, WindAxes, plot_windrose

(ggplot(data=df) +
aes(x='u-wind',y='v-wind', color='windspeed') +
geom_point()
)

output_13_0

风玫瑰图

通过风玫瑰图,我们可以更加直观地看到风向、风速的分布情况,得到与上面相同的结论。

1
2
3
4
5
ax = WindroseAxes.from_ax()
ax.bar(df['direction'], df['windspeed'], normed=True,
opening=0.8,
bins=np.arange(0.01,8,1), cmap=cm.RdYlBu_r, lw=3)
ax.set_legend()

output_15_1

除了可以画直方图以外,还可以画等高线图,具体命令如下:

1
2
3
4
5
_ = plot_windrose(df, kind='contour', var_name='windspeed',
direction_name='direction',
normed=True,
bins=np.arange(0.01,8,1),
cmap=cm.RdYlBu_r, lw=3)

output_17_0

此外,windrose库具有简单的统计功能,可以采用Weibull分布拟合风速的概率密度直方图。

1
2
3
4
5
6
bins = np.arange(0,50+1,1)
bins = bins[1:]
bins
_ = plot_windrose(df, kind='pdf', var_name='windspeed',
direction_name='direction',
bins=bins)
C:\ProgramData\Anaconda3\lib\site-packages\windrose\windrose.py:620: VisibleDeprecationWarning:

Passing `normed=True` on non-uniform bins has always been broken, and computes neither the probability density function nor the probability mass function. The result is only correct if the bins are uniform, when density=True will produce the same result anyway. The argument will be removed in a future version of numpy.

output_19_1

最后,我们将2007年一年的数据按照月度分别绘制风玫瑰图,可以看出风向和风力的月度变化。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import datetime

nrows, ncols = 3, 4
fig = plt.figure(facecolor='grey',figsize=(30, 16))
bins = np.arange(0.01, 10, 1)
year = 2007
fig.suptitle("Wind speed - %d" % year)
for month in range(1, 13):
ax = fig.add_subplot(nrows, ncols, month, projection="windrose")
title = datetime.datetime(year, month, 1).strftime("%b")
ax.set_title(title)
try:
df_month = df[(df['Year']==year)&(df['Month']==month)]
except KeyError:
continue
direction = df_month["direction"].values
var = df_month["windspeed"].values
# ax.contour(direction, var, bins=bins, colors='black', lw=3)
ax.contourf(direction, var, bins=bins, cmap=cm.RdYlBu_r)
ax.contour(direction, var, bins=bins, colors="black")

plt.show()

output_21_0

上图除了验证了前面的结论以外,还可以发现11月和3月的风力最大、风向最为集中,而非1月或者12月。7月份风向更加偏北,东北风、(东)南风的比例大大增加,但是风的整体强度不大。

之所以呈现出这样的特点,与站点所处地理位置的气候特点密切相关。该站点位于落基山脉内,北纬39度多,位于中纬度地带。中学地理曾经学过,中纬度环流与低纬度和极地环流不同,并非完整闭合,但是在上空主要由西风带主导。显然该位置自然而然以西风为主。

北美大陆的气压配置图式与亚欧大陆相似,具有四个活动中心,即:两个副极地低压中心—北大西洋冰岛低压和北太平洋阿留申低压;两个副热带高压中心—北大西洋亚速尔高压和北太平洋夏威夷高压。另外,在大陆内部也有一个冬高夏低、冬夏交替的气压活动中心。冬季,海洋温度高于大陆温度,西风更加强盛;夏季,大陆温度高于海洋温度,西风活动减弱。查阅有关资料可知,

  • 冬季,太平洋沿岸,主要吹海风,其中北纬40°以北多西南风,北纬40°以南为西风和西北风,到北纬30°以南转为东北风;
  • 夏季,太平洋沿岸,北纬50°以北吹西南风,北纬50°~40°之间由西风转为西北风,北纬40°以南转为北风和东北风。

Map_prevailing_winds_on_earth

前面说过该站点位于北纬40度附近,因此冬季主要为西风和西北风,而在夏季北风、西北风、东北风甚至南风都有(南风的整体强度很小),其具体原因有待进一步学习。夏季的风向比较紊乱,一方面是由于此地本来以西风为主,虽然西风减弱,但是仍然具有相当强的实力,另一方面,北美大陆面积较小,海陆热力差异不如亚洲显著,因此风的强度有“中和”的感觉。当然,一年的数据也存在偶然性,需要多年的数据加以分析。

小结

通过使用python的windrose库,本文分析了美国科罗拉多州落基山脉一个站点2007全年的风力特点,风玫瑰图的确是直观高效。而且还发现,风力分布的特点可以用中学学过的地理知识得以解释,真的让人欢欣鼓舞。实际上,除了分析单个站点一年的分布情况以外:

  • 往细里说,可以以天为单位,分析每天的风力波动情况,以及每天随着季节的变化;
  • 往大里说,可以分析不同年的风力变化情况,分析厄尔尼诺、拉尼娜等大尺度的影响以及全球变化的影响;
  • 往空间里说,可以分析相邻位置站点之间的关系。
  • 此外,还可以分析极端风力的分布用来指导风力发电、天气指数保险等业务。

参考资料

  1. https://www.linkedin.com/pulse/wind-rose-chonghua-yin/
  2. https://www.nrel.gov/grid/western-wind-data.html
  3. https://github.com/python-windrose/windrose
  4. https://www.wcc.nrcs.usda.gov/climate/windrose.html
  5. https://en.wikipedia.org/wiki/Atmospheric_circulation
  6. https://www.pexels.com/photo/woman-holding-black-flag-1571734/
  7. https://en.wikipedia.org/wiki/Wind_rose
(美好的断背山故事就发生在这里)

Banff