添加新云天气象小编微信或QQ:130188121,及时获取或发布气象升学、就业、会议、征稿及学术动态信息!最新热点文章:行业动态 | 2020中国气象现代化建设科技博览会行业动态 | “远征杯”中国信用防雷宣传活动开锣了!气象招聘 | 中南空管局气象中心2020年校园招聘公告

今天我们来讲讲风数据的简单处理和分析。通过这个案例,你将知道一些与风数据处理和分析有关的Python函数库和绘图方法。具体内容如下:

1)如何从网络上获取数据并读取格式化数据(reading data)

2)如何处理时间变量(datetime variable)

3)如何判别异常值和去除异常值(Outlier)

4)如何使用Pandas.DataFrame来筛选、整合、选择数据

5)如何绘制风玫瑰图

6)如何绘制数据的统计分布曲线

7)如何从数据中获取Weibull分布参数

8)如何绘制16位风向统计柱状图

9)如何绘制单点风矢量动画和GIF输出

10)如何绘制箱式统计图(boxplot)

11)风的矢量分解函数的使用

Python编程语言已经成为世界上最流行和受欢迎的编程语言。它的灵活性和易用性已经强大的函数库吸引了数据分析爱好者。今天我们一起来看一例使用Python语言来处理和分析风数据的一个案例。希望这个案例能够帮助到大家。

风数据是我们应用气象专业的同行们经常要接触的。相比温度、降水量、太阳辐射等气象要素,风要素的重要特征是它是一个矢量要素,有方向有大小。风方向从正北方向为0°开始,顺时针转向360°,因此正东方向就对应风向90°,正南为180°,正西为270°,正北为0°。在气象上通常将风向划分为16个方向,用符号N,NNE,NE,...来表示。风速则根据风速大小划分等级,比如国际通用的风力等级:蒲福风级(https://baike.baidu.com/item/蒲福风级)。因此有了风向、风速的分类分级,我们就可以对风要素进行分析,获取不同地方的风场特征。其中最重要的风场特征表现形式是风玫瑰图。下面我们就风数据的读取、预处理和分析来做一个案例。

# 加载一些常用的Python函数库

# numpy是支持多维数据存储、运算、分析函数库

# pandas是结构化数据的存储、运算、分析函数库

# matplotlib是比用绘图函数库

# seaborn是绘图函数库

# warnings是运行警告函数库

import numpy as np import pandas as pd import matplotlib.pyplot as plt import seaborn as snsimport warnings 

# 运行环境设置:在Notebook中抑制警告输出

warnings.filterwarnings('ignore') 

# 在notebook中显示绘制的图像

%matplotlib

# 加载风数据。风数据存放在网络上。注:本案例的风数据是在原始数据基础上增加了噪声

url = 'https://raw.githubusercontent.com/yangsbin/Meteo_data_analysis/master/data/wind_data.txt'

# 通过Pandas的read_csv函数读取格式化数据,参数中sep是读取的原数据列的分隔符参数定义, header是头行(None就是无头行),names定义了每个数据列的名称;WD定义为风向;WS定义为风速

wind_data = pd.read_csv(url, sep = r'\s+', header = None, names = ['Year','Month','Day','Hour', 'WD','WS'])

# 原始数据中风速是10倍值,因此将读取后的数据中的风速列数据除10转化为正常值

wind_data.WS = wind_data.WS/10.0    

# 浏览wind_data数据变量的前5行的数值

wind_data.head()   

# 加载日期和时间函数库,处理与日期和时间有关的变量或数值

from datetime import datetime   

# 定义一个空列表变量,用于存储时间变量

datetimes = []

# 定义year_v变量存放原数据中的Year数据列

year_v = wind_data['Year'].values    

# 定义month_v变量存放原数据中的Month数据列

month_v = wind_data['Month'].values   

# 定义day_v变量存放原数据中的Day数据列

day_v = wind_data['Day'].values   

# 定义hour_v变量存放原数据中的Hour数据列

hour_v = wind_data['Hour'].values     

# 下面的循环是整合各时间要素变量,每个时间值都是“年月日时”

# List数据类型的append方法就是把每个时间值串起来形成一个列表

for i in range(0, len(year_v)):    datetimes.append(datetime(year_v[i], month_v[i], day_v[i], hour_v[i]))       

# 把整合后的时间变量作为导入数据的行索引,在气象数据的处理上很有用,因为气象数据多是时间序列数据

wind_data.index = pd.Series(datetimes)  

# 给这个刚定义的索引命名

wind_data.index.name = 'Datetime'

# 浏览前5行的数值

wind_data.head()

# 根据年和月进行分组统计,WD代表风向,WS代表风速

wind_data[['Year','Month','WD', 'WS']].groupby(['Year', 'Month']).describe().head()

# 下面绘制图形,看看有没有奇异值(outliers)

# 首先创建一个新的绘图区

fg = plt.figure()

# 创建组图中的第一个图

plt.subplot(121)plt.plot(wind_data.WD)plt.ylabel('Values')plt.title('WD')

# 创建组图中的第二个

plt.subplot(122)plt.plot(wind_data.WS)plt.ylabel('Values')plt.title('WS')

# 组图布局设置

plt.subplots_adjust(top=0.92, bottom=0.41, left=0.10, right=0.95, hspace=0.25, wspace=0.55)

# 从上图可以看到有很多异常值。定义异常值:第一个是风向角度超过360°的,第二个是风速异常大的超过1000的

outlier_index = np.logical_or(wind_data['WD'] > 360, wind_data['WS'] > 1000)wind_data = wind_data.loc[~outlier_index, :]print("{0} rows of data were removed".format(len(outlier_index)) )
17544 rows of data were removed

# 对剔除了异常值后的数据进行再次统计,可以看出,风向和风速统计值正常了

wind_data[['Year','Month','WD', 'WS']].groupby(['Year', 'Month']).describe().head()

# 再画图看看,这回数值都正常了

fg = plt.figure()plt.subplot(121)plt.plot(wind_data['WD'], linewidth=0.2)plt.ylabel('Values')plt.title('WD')plt.subplot(122)plt.plot(wind_data['WS'])plt.ylabel('Values')plt.title('WS')plt.subplots_adjust(top=0.92, bottom=0.41, left=0.10, right=0.95, hspace=0.25, wspace=0.55)

# 下面以2012年数据为例,我们做一些分析和统计

# 首先,选择2012年的5列数据组成一个新的Pandas.DataFrame数据变量

wind_2012 = wind_data.loc[wind_data['Year']==2012, ['Month','Day','Hour', 'WD', 'WS']]

# 然后绘制画箱式图,其目的是查看各月份风向和风速数据的统计分布特征(中值、分布对称性、奇异值、分布范围、集中性);使用了Seaborn绘图函数库的boxplot函数绘制该变量的统计箱式图

fg = plt.figure()plt.subplot(121)wd_2012 = wind_data[['Month','WD']]sns.boxplot(x = 'WD', y = 'Month', data = wd_2012, orient = 'h', fliersize=0.5, linewidth = 0.7)plt.subplot(122)ws_2012 = wind_data[['Month','WS']]ax = sns.boxplot(x = 'WS', y = 'Month', data = ws_2012, orient = 'h', fliersize=0.5, linewidth = 0.7)ax.set_xlabel('WS (m/s)')plt.subplots_adjust(top=0.92, bottom=0.21, left=0.10, right=1.0, hspace=0.25, wspace=0.45)

# 数据统计分布曲线的绘制;使用Seaborn库的distplot函数绘制2012年风向的统计分布曲线

fg = plt.figure()plt.subplot(121)ax = sns.distplot(wind_2012.WD)plt.ylabel('Probability')plt.grid()plt.subplot(122)ax = sns.distplot(wind_2012.WS)plt.ylabel('Probability')plt.xlabel('WS (m/s)')plt.grid()plt.subplots_adjust(top=0.92, bottom=0.21, left=0.10, right=1.0, hspace=0.25, wspace=0.45)

# 比较2012年1月和7月的风场;分别提取1月和7月的风向、风速数据

fg = plt.figure()wd_Jan = wind_2012.loc[wind_2012['Month'] == 1, ['Month','WD']]wd_Jul = wind_2012.loc[wind_2012['Month'] == 7, ['Month','WD']]plt.subplot(121)sns.distplot(wd_Jan.WD)sns.distplot(wd_Jul.WD)plt.ylabel('Probability')plt.grid()plt.legend(['Jan','Jul'], frameon = False)ws_Jan = wind_2012.loc[wind_2012['Month'] == 1, ['Month','WS']]ws_Jul = wind_2012.loc[wind_2012['Month'] == 7, ['Month','WS']]plt.subplot(122)sns.distplot(ws_Jan.WS)sns.distplot(ws_Jul.WS)plt.ylabel('Probability')plt.xlabel('WS (m/s)')plt.grid()plt.legend(['Jan','Jul'], frameon = False)plt.subplots_adjust(top=0.92, bottom=0.21, left=0.10, right=1.0, hspace=0.25, wspace=0.45)

# 绘制风玫瑰

# 为了绘制风玫瑰,需要加载风玫瑰绘图函数库

from windrose import WindroseAxesimport matplotlib.cm as cm

# 绘制1月的风玫瑰,图上数值为百分比;该图采用堆积柱状图表示不同风速区间的百分比

ax = WindroseAxes.from_ax()ax.bar(wd_Jan.WD, ws_Jan.WS, normed=True, opening=0.8, edgecolor='black')ax.set_legend()

# 绘制1月的风玫瑰,图上数值为在各风段区间出现的风速的总数;采用等值线图绘制风玫瑰,风速被划分为9个等份,contourf为填充图;采用等值线图绘制风玫瑰,风速被划分为9个等份,contour为线图

ax = WindroseAxes.from_ax()ax.contourf(wd_Jan.WD, ws_Jan.WS, bins=np.arange(0,9,1), cmap=cm.hot)ax.contour(wd_Jan.WD, ws_Jan.WS, bins=np.arange(0,9,1), colors = 'black', lw=1)ax.set_title('January')ax.set_legend()

# 绘制7月的风玫瑰,图上数值为在各风段区间出现的风速的总数;演示另一种绘图函数plot_windrose

df = pd.DataFrame({'speed':ws_Jul.WS.values, 'direction':wd_Jul.WD.values})ax = plot_windrose(df, kind = 'contour', bins=np.arange(0, 9, 1), cmap=cm.jet, lw=1)ax.set_title('July')

# 绘制1月和7月堆积柱状图式的风玫瑰组图

fg = plt.figure()ax1 = fg.add_subplot(1,2,1, projection='windrose')ax1.bar(wd_Jan.WD, ws_Jan.WS, normed=True, opening=0.8, edgecolor='white')ax1.set_title('January', pad = 20)ax2 = fg.add_subplot(1,2,2, projection='windrose')ax2.bar(wd_Jul.WD, ws_Jul.WS, normed=True, opening=0.8, edgecolor='white')ax2.set_title('July', pad = 20)plt.subplots_adjust(top=1, bottom=0, left=0.0, right=1.0, hspace=0.25, wspace=0.45)

# 绘制1月和7月等值线图式的风玫瑰组图

fg = plt.figure()ax_Jan = fg.add_subplot(1,2,1, projection='windrose')ax_Jan.contourf(wd_Jan.WD, ws_Jan.WS, bins = np.arange(0,9,1.5), cmap = cm.hot)ax_Jan.contour(wd_Jan.WD, ws_Jan.WS, bins = np.arange(0,9,1.5), colors = 'black', lw = 0.5)ax_Jan.set_title('January', pad = 20)ax_Jul = fg.add_subplot(1,2,2, projection = 'windrose')ax_Jul.contour(wd_Jul.WD, ws_Jul.WS, bins = np.arange(0,9,1.5), colors = 'black', lw = 0.5)ax_Jul.set_title('July', pad = 20)plt.subplots_adjust(top=1, bottom=0, left=0.0, right=1.0, hspace=0.25, wspace=0.45)

# 按16方位风向绘制风向频次统计柱状图

ax_Jan.bar(wd_Jan.WD, ws_Jan.WS, normed=True, nsector=16)table_Jan = ax_Jan._info['table']wd_freq_Jan = np.sum(table_Jan, axis=0)direction_Jan = ax_Jan._info['dir']plt.figure(figsize=(10,4))plt.bar(np.arange(16), wd_freq_Jan, align='center', facecolor = 'green')plt.xticks(np.arange(16))xlabels = ['N','NNE','NE','ENE','E','ESE','SE','SSE','S','SSW','SW','WSW','W','WNW','NW','NNW']_ = plt.gca().set_xticklabels(xlabels)_ = plt.text(x = 14, y = 17.5, s = 'January')_ = plt.ylabel('Frequency (%)')

# 有风速观测数据,反推风速统计分布—Weibull统计分布参数;params为输出的Weibull统计分布参数,包括shape、loc、scale

from windrose import WindAxesax = WindAxes.from_ax()bins = np.arange(0, 9+1, 0.5)bins = bins[1:]ax, params = ax.pdf(ws_Jan.WS, bins = bins)ax.set_xlabel('WS (m/s)')ax.set_ylabel('Probability')print(params)
(1, 2.6614301902227524, 0, 3.734483068109758)

# 采用scipy函数库中的统计函数库来拟合风速的统计分布参数

from scipy import statsfg = plt.figure()plt.subplot(121)

# 对观测的风速数据的统计分布进行Weibull统计分布拟合,获取统计分布参数

shape, loc, scale = stats.weibull_min.fit(ws_Jan.WS, floc=0)x = np.arange(0, 10, 0.01)

# 利用拟合获得的参数,绘制Weibull统计分布曲线

sns.lineplot(x, stats.weibull_min.pdf(x, c = shape, scale = scale, loc = loc))

# 另一种方法是直接绘制观测的风速数据的Weibull统计分布拟合曲线,这个方法不返回统计分布参数

sns.distplot(ws_Jan.WS, bins = 30, fit = stats.weibull_min, kde = False, hist = True)plt.xlabel('WS (m/s)')plt.ylabel('Probability')plt.title('January')plt.legend(['Weibull 1','Weibull 2'], frameon = False)plt.subplot(122)shape, loc, scale = stats.weibull_min.fit(ws_Jul.WS, floc=0)x = np.arange(0, 10, 0.01)sns.lineplot(x, stats.weibull_min.pdf(x, c = shape, scale = scale, loc = loc))sns.distplot(ws_Jul.WS, bins = 30, fit = stats.weibull_min, kde = False, hist = True)plt.xlabel('WS (m/s)')plt.ylabel('Probability')plt.title('July')plt.legend(['Weibull 1','Weibull 2'], frameon = False)plt.subplots_adjust(top=0.92, bottom=0.21, left=0.10, right=1.0, hspace=0.25, wspace=0.45)

# 风向的矢量分解,调用了Ute_WRF的库函数

# https://github.com/blaylockbk/Ute_WRF/tree/master/functions

# 库函数wind_spddir_to_uv的定义

def wind_spddir_to_uv(wspd, wdir):    """    calculated the u and v wind components from wind speed and direction    Input:        wspd: wind speed        wdir: wind direction    Output:        u: u wind component        v: v wind component    """        rad = 4.0*np.arctan(1)/180.    u = -wspd*np.sin(rad*wdir)    v = -wspd*np.cos(rad*wdir)return u,v

# 设置绘图环境

%matplotlib

# 矢量分解函数的调用

u1, v1 = wind_spddir_to_uv(ws_Jan.WS, wd_Jan.WD)

# 绘制矢量动画,即显示不同时刻风矢量的方向和大小

plt.ionfg = plt.figure()ax = fg.add_subplot(111)for i in range(0, len(u1)):    # 清楚当前绘图区    plt.clf()    # 矢量绘图函数quiver    plt.quiver(-u1[i], -v1[i], scale=20.0, color = 'blue')    # 设置横坐标范围    plt.xlim([-2,2])    # 设置纵坐标范围    plt.ylim([-2,2])    # 设置图中文字信息,显示年月日时    plt.text(x = 0.6, y = 0.0, s='{0}-{1}-{2}-{3}'.format(            ws_Jan.index[i].year, ws_Jan.index[i].month, ws_Jan.index[i].day,             ws_Jan.index[i].hour))    # 设置图中文字信息,显示(U,V)    plt.text(x = 0.6, y = -1.5, s='(U,V) = ({0},{1})'.format(round(u1[i],2), round(v1[i],2)))    # 设置图中文字信息,显示风向(度)    plt.text(x = 0.6, y = -0.5, s='Wind direction: {0}'.format(round(wd_Jan.WD[i], 2)))    # 设置图中文字信息,显示风速(m/s)    plt.text(x = 0.6, y = -1.0, s='Wind speed: {0} (m/s)'.format(round(ws_Jan.WS[i], 2)))    # 保存每一个图为一个png格式的图像文件    plt.savefig('{0}.png'.format(i))    fg.canvas.draw()    # 刷新绘图区    fg.canvas.flush_events()

# 风矢量的GIF动画输出

# 加载glob函数库和imageio图像输入输出函数库

import globimport imageio

# 输出GIF

graphs = []for i in range(0, len(u1)):    # filename记录的是当前目录下所有风矢量图    filename = str('{0}.png'.format(i))    # 把所有风矢量图读取到内存,并串起来形成一个列表    graphs.append(imageio.imread(filename))# 定义输出的GIF文件名output_file = 'Gif_{0}.gif'.format(datetime.today())# 使用mimsave函数输出动画imageio.mimsave(output_file, graphs, duration = 0.1, loop = 1)

上述代码在Python 3.6以上测试通过,源程序可以访问作者的GitHub主页下的Meteo_data_analysis:https://github.com/yangsbin/Meteo_data_analysis

如果对本案例有什么补充和建议,欢迎留言?。谢谢!

往期回顾:

气象招聘 | 中国民用航空华东地区空中交通管理局招聘气象岗位宣讲会

气象招聘 | 天象科技2019秋冬季人才招聘计划

行业动态 | “远征杯”中国信用防雷宣传活动开锣了!

2020届气象本科考研与就业QQ群:9301072622020届气象研究生毕业就业QQ群:3465774272021届气象本科考研与就业QQ群639522239

python subplot_气象编程 | 一个简单的风数据处理和分析案例(Python版)相关推荐

  1. 用python处理excel数据做函数_如何使用python通过函数式编程完成excel中的数据处理及分析工作...

    Excel是数据分析中最常用的工具,本篇文章通过python与excel的功能对比介绍如何使用python通过函数式编程完成excel中的数据处理及分析工作.在Python中pandas库用于数据处理 ...

  2. python程序30行_30行Python代码,打造一个简单的微信群聊助手,简单方便

    大家都知道,最近代码君迷上了Python,一直在研究这门语言,还是那句话,人生苦短,我学Python,今天代码君要教大家一个黑科技,30行代码实现自己定制的微信群聊助手,这个助手有什么用呐,就是用来活 ...

  3. 通过汇编一个简单的C程序,分析汇编代码理解计算机是如何工作的

    实验目的: 通过反汇编一个简单的C程序,分析汇编代码理解计算机是如何工作的 实验过程: 通过vi程序进行编程: int g(int x) { return x + 3; } int f(int x) ...

  4. c理c利用计算机怎么弹,通过汇编一个简单的C程序,分析汇编代码理解计算机是如何工作的...

    通过汇编一个简单的C程序,分析汇编代码理解计算机是如何工作的 计算机的工作方式: 现代计算机的基本体系结构都是采用冯诺依曼结构,冯诺依曼的设计思想最重要之处是"存储程序"的这个概念 ...

  5. android商品数量加减,微信小程序实现一个简单的商品数量加减案例

    简介 这是一个用微信小程序原生代码实现的数量加减demo,主要是用于商品购物车或者商品详情修改数量使用,很简单哦~~~. 核心js方法说明addCount(增加数量) delCount (减少数量) ...

  6. ROS2入门教程—创建一个简单的订阅者和发布者(C++版)

    ROS2入门教程-创建一个简单的订阅者和发布者(C++版) 1 创建功能包 2 创建发布者节点 3 设置发布者节点依赖项 4 设置发布者节点编译规则 5 创建订阅者 6 编译并运行   节点是通过RO ...

  7. python编写赛车游戏单机版_使用Python中OrderedDict模拟一个简单的竞速游戏排名

    上一篇,我们梳理了Python中关于字典排序的一些常用方法(杂乱无章的数据结构如何进行排序,简明讲述Python字典排序那些事).其中,我们讲到了Python的collections模块中的Order ...

  8. 扩展Python模块系列(二)----一个简单的例子

    本节使用一个简单的例子引出Python C/C++ API的详细使用方法.针对的是CPython的解释器. 目标:创建一个Python内建模块test,提供一个功能函数distance, 计算空间中两 ...

  9. python 处理csv文件 一个简单的数据处理任务

    一个简单的数据处理任务 任务说明 Step 1 Step 2 Step 3 Step 4 一.将文件类型转化为csv类型 二.删除异常数据写入text1 1.思路 2.代码 3.text1中数据 三. ...

最新文章

  1. 安卓串口中InputStream数据接收不完整
  2. 暗渡陈仓:用低消耗设备进行破解和渗透测试1.2.2 渗透测试工具集
  3. 机器学习:数据驱动的科学
  4. 关于MAC升级后,vim更新插件报错
  5. [CodeForces 567C] Geometric Progression
  6. html5音频文件生成波形图代码,HTML5/D3.js 可视音频波形柱状图
  7. 实验报告类与对象水井问题_物业设施设备巡检检查对象、周期和频次
  8. c语言中将函数指针作为形参_在C中将有效指针作为NULL指针
  9. 【投资策略】2022 年大类资产配置展望:稳中求进-中金公司
  10. [CareerCup] 7.7 The Number with Only Prime Factors 只有质数因子的数字
  11. java图片色差_java – JPEG图像的颜色错误
  12. 人工智能应用在会计工作中的优势
  13. java制作扫雷游戏中埋雷的难点_java 扫雷游戏源码案例项目
  14. 拓端tecdat:R语言深度学习卷积神经网络 (CNN)对 CIFAR 图像进行分类:训练与结果评估可视化
  15. oracle grant的用法,oracle grant总结
  16. java递归算法经典实例_java简单编程题问第五个人多少岁?java递归算法经典实例...
  17. 【转载】52nlp博客上的资源
  18. 多目标优化算法:多目标非洲秃鹫优化算法MOAVOA(提供Matlab代码)
  19. Python 股票分析快速入门
  20. 新版jadx-gui导入dex会提示Bad checksum

热门文章

  1. 手持GPS坐标系统的转换与应用
  2. python批量提取word指定内容到excel_(转)用python批量读取word文档并整理关键信息到excel表格...
  3. halcon python_使用pythonnet调用halcon脚本
  4. 【Matlab 图像】同时显示两个视频
  5. 2.7 RMSprop-深度学习第二课《改善深层神经网络》-Stanford吴恩达教授
  6. 6.6 二分 K-Means 算法-机器学习笔记-斯坦福吴恩达教授
  7. RS-232串口线与以太网的八芯双绞线的对比,为什么不使用串口线来连接电脑和路由器?
  8. 人工智能最佳学习实践
  9. 对WIFI通信的一些理解(经常更新修改)
  10. C#子线程中更新ui