找回密码
 立即注册
搜索
楼主: bala

【Python】简单的Python处理气象数据的教程

[复制链接]

5

主题

133

回帖

485

积分

热带低压-GW

积分
485
发表于 2024-4-6 23:30 | 显示全部楼层
佬!我学完就能画图了!

点评

我也是!目前就卡这块了!  发表于 2024-4-7 06:22
“风雨中报紧自由”

2

主题

28

回帖

173

积分

管理员-厄尔尼诺

积分
173
发表于 2024-4-7 09:33 | 显示全部楼层
我建议大佬开一个单独的帖子,贴一点佬写的可以直接运行出图的代码,然后让大家在学习了基础知识后来问问题。问题中学习效果是最好的,一个个章节的学太慢,而且没有持续的积极反馈,很容易打击积极性。
个人编程论坛 pfun.sunrui.ink

2

主题

38

回帖

284

积分

热带低压

积分
284
 楼主| 发表于 2024-4-7 10:03 | 显示全部楼层
greatbody 发表于 2024-4-7 09:33
我建议大佬开一个单独的帖子,贴一点佬写的可以直接运行出图的代码,然后让大家在学习了基础知识后来问问题 ...

后面几章就开始进入正题了

点评

同样期待!!学完就可以画图了!!  发表于 2024-4-7 19:12
期待!!!  发表于 2024-4-7 10:48
头秃

2

主题

38

回帖

284

积分

热带低压

积分
284
 楼主| 发表于 2024-4-7 11:09 | 显示全部楼层
本帖最后由 bala 于 2024-9-18 16:58 编辑

(...接上一节)
3.Pandas教程
我们建议学习基础教程:https://www.runoob.com/pandas/pandas-tutorial.html
后面不管是数据处理还是绘图,pandas将会是一个非常非常重要的库,广泛应用在学术、金融、统计学等各个数据分析领域。Pandas 的主要数据结构是 Series (一维数据)与 DataFrame(二维数据)。
首先我们打开cmd,输入
  1. pip install pandas
复制代码
,安装完成后即可在开发环境中使用。

首先我们了解一下Series和Dataframe:
Series: 类似于一维数组或列表,是由一组数据以及与之相关的数据标签(索引)构成。Series 可以看作是 DataFrame 中的一列,也可以是单独存在的一维数据结构。
我们可以打个比方理解为是只有两列的excel单元格,一列索引,一列数据。
DataFrame: 类似于一个二维表格,它是 Pandas 中最重要的数据结构。DataFrame 可以看作是由多个 Series 按列排列构成的表格,它既有行索引也有列索引,因此可以方便地进行行列选择、过滤、合并等操作。
我们也可以理解为有多行多列的excel表格的形式。
(当然,我们常用的excel表格内的数据与dataframe可以快速简便的转换,后面的小节会提到)

(1)pandas读取和写入数据
①直接读取
我们有这么一坨数据:
  1. [{"type":"A.01","Datetime":"2024/02/17 12","TEM":12.7},{"type":"A.01","Datetime":"2024/02/17 13","TEM":10.6},{"type":"A.01","Datetime":"2024/02/17 14","TEM":10.6},{"type":"A.01","Datetime":"2024/02/17 15","TEM":8.7},{"type":"A.01","Datetime":"2024/02/17 16","TEM":7.6},{"type":"A.01","Datetime":"2024/02/17 17","TEM":9.8},{"type":"A.01","Datetime":"2024/02/17 18","TEM":11.0},{"type":"A.01","Datetime":"2024/02/17 19","TEM":10.7},{"type":"A.01","Datetime":"2024/02/17 20","TEM":10.7},{"type":"A.01","Datetime":"2024/02/17 21","TEM":10.7},{"type":"A.01","Datetime":"2024/02/17 22","TEM":10.7},{"type":"A.01","Datetime":"2024/02/17 23","TEM":10.5},{"type":"A.01","Datetime":"2024/02/18 00","TEM":10.4},{"type":"A.01","Datetime":"2024/02/18 01","TEM":11.3},{"type":"A.01","Datetime":"2024/02/18 02","TEM":14.5},{"type":"A.01","Datetime":"2024/02/18 03","TEM":16.5},{"type":"A.01","Datetime":"2024/02/18 04","TEM":18.0},{"type":"A.01","Datetime":"2024/02/18 05","TEM":18.8},{"type":"A.01","Datetime":"2024/02/18 06","TEM":19.4},{"type":"A.01","Datetime":"2024/02/18 07","TEM":20.0},{"type":"A.01","Datetime":"2024/02/18 08","TEM":19.5},{"type":"A.01","Datetime":"2024/02/18 09","TEM":18.7},{"type":"A.01","Datetime":"2024/02/18 10","TEM":17.9},{"type":"A.01","Datetime":"2024/02/18 11","TEM":16.5},{"type":"A.01","Datetime":"2024/02/18 12","TEM":12.9}]
复制代码

这是一坨列表嵌套字典的数据,每一个{字典}是最外层[列表]的一个值,将其转为dataframe数据非常简单,只需要下面的代码:
  1. import pandas as pd
  2. a = [{"type":"A.01","Datetime":"2024/02/17 12","TEM":12.7},{"type":"A.01","Datetime":"2024/02/17 13","TEM":10.6},{"type":"A.01","Datetime":"2024/02/17 14","TEM":10.6},{"type":"A.01","Datetime":"2024/02/17 15","TEM":8.7},{"type":"A.01","Datetime":"2024/02/17 16","TEM":7.6},{"type":"A.01","Datetime":"2024/02/17 17","TEM":9.8},{"type":"A.01","Datetime":"2024/02/17 18","TEM":11.0},{"type":"A.01","Datetime":"2024/02/17 19","TEM":10.7},{"type":"A.01","Datetime":"2024/02/17 20","TEM":10.7},{"type":"A.01","Datetime":"2024/02/17 21","TEM":10.7},{"type":"A.01","Datetime":"2024/02/17 22","TEM":10.7},{"type":"A.01","Datetime":"2024/02/17 23","TEM":10.5},{"type":"A.01","Datetime":"2024/02/18 00","TEM":10.4},{"type":"A.01","Datetime":"2024/02/18 01","TEM":11.3},{"type":"A.01","Datetime":"2024/02/18 02","TEM":14.5},{"type":"A.01","Datetime":"2024/02/18 03","TEM":16.5},{"type":"A.01","Datetime":"2024/02/18 04","TEM":18.0},{"type":"A.01","Datetime":"2024/02/18 05","TEM":18.8},{"type":"A.01","Datetime":"2024/02/18 06","TEM":19.4},{"type":"A.01","Datetime":"2024/02/18 07","TEM":20.0},{"type":"A.01","Datetime":"2024/02/18 08","TEM":19.5},{"type":"A.01","Datetime":"2024/02/18 09","TEM":18.7},{"type":"A.01","Datetime":"2024/02/18 10","TEM":17.9},{"type":"A.01","Datetime":"2024/02/18 11","TEM":16.5},{"type":"A.01","Datetime":"2024/02/18 12","TEM":12.9}]
  3. df = pd.DataFrame(a)
  4. print(df)
复制代码


结果:
    type       Datetime   TEM
0   A.01  2024/02/17 12  12.7
1   A.01  2024/02/17 13  10.6
2   A.01  2024/02/17 14  10.6
3   A.01  2024/02/17 15   8.7
4   A.01  2024/02/17 16   7.6
5   A.01  2024/02/17 17   9.8
6   A.01  2024/02/17 18  11.0
7   A.01  2024/02/17 19  10.7
8   A.01  2024/02/17 20  10.7
9   A.01  2024/02/17 21  10.7
10  A.01  2024/02/17 22  10.7
11  A.01  2024/02/17 23  10.5
12  A.01  2024/02/18 00  10.4
13  A.01  2024/02/18 01  11.3
14  A.01  2024/02/18 02  14.5
15  A.01  2024/02/18 03  16.5
16  A.01  2024/02/18 04  18.0
17  A.01  2024/02/18 05  18.8
18  A.01  2024/02/18 06  19.4
19  A.01  2024/02/18 07  20.0
20  A.01  2024/02/18 08  19.5
21  A.01  2024/02/18 09  18.7
22  A.01  2024/02/18 10  17.9
23  A.01  2024/02/18 11  16.5
24  A.01  2024/02/18 12  12.9


这个形式有点像excel,大胆点,跟excel基本上一样!
②读取csv
我地有一坨温江的探空数据(见附件),格式为CSV,打开方式有很多,我们可以直接用wps或者excel打开,当然你也可以用编程软件打开,例如vscode等等。
(注意:打开时可能会遇到编码的问题,例如:UnicodeDecodeError: 'utf-8' codec can't decode byte 0xb3 in position 0: invalid start byte,意思是无法使用UTF-8解码,我们可以加上encoding参数,具体的错误代码可复制自行百度)
用pandas打开方式如下:
  1. import pandas as pd
  2. df = pd.read_csv("2023030700-56187.csv")
  3. print(df)
复制代码

输出结果:
                   time  longitude  latitude  pressure  geopotential height  temperature dew point temperature ice point temperature relative humidity  humidity wrt ice mixing ratio  wind direction  wind speed
0   2023-03-06 23:15:12    103.870    30.750     954.5                  549         13.1                  12.0                  12.0                93                93         9.27             0.0         0.0   
1   2023-03-06 23:15:20    103.870    30.750     949.2                  595         13.1                  11.3                  11.3                89                89         8.89             0.0         0.0   
2   2023-03-06 23:15:42    103.870    30.750     934.9                  725         12.3                  10.9                  10.9                91                91         8.79            81.0         1.6   
3   2023-03-06 23:15:57    103.870    30.750     925.0                  813         12.1                  10.2                  10.2                88                88         8.48            87.0         1.5   
4   2023-03-06 23:16:14    103.869    30.750     913.8                  914         11.6                   9.8                   9.8                89                89         8.35            94.0         1.4   
..                  ...        ...       ...       ...                  ...          ...                   ...                   ...               ...               ...          ...             ...         ...   
94  2023-03-06 23:55:12    104.354    30.770     109.1                15877        -69.9                                                                               0                        266.0        44.1   
95  2023-03-06 23:55:47    104.371    30.770     104.9                16116        -71.5                                                                               0                        269.0        44.2   
96  2023-03-06 23:56:12    104.383    30.771     101.9                16287        -71.2                                                                               0                        271.0        44.3   
97  2023-03-06 23:56:21    104.388    30.771     101.0                16348        -71.1                                                                               0                        271.0        44.4   
98  2023-03-06 23:56:29    104.391    30.771     100.0                16404        -71.6                                                                               0                        271.0        44.4   

[99 rows x 13 columns]

③读取excel表格
方法基本上跟上面一样
  1. import pandas as pd
  2. df = pd.read_excel("hainan-2024040316.xlsx")
  3. print(df)
复制代码

输出结果:
     type Station_Id_C Station_Name    Lat     Lon   Alti       Datetime     PRS  PRS_Sea  PRS_Max  PRS_Min   TEM  TEM_Max  TEM_Min   RHU  PRE_1h  PRE_24h  WIN_D_INST_Max  WIN_S_Inst_Max  VIS  VIS_Min
0     A.01        N2253       三江良口和里  25.74  109.49  200.3  2024/04/03 16   986.5   1009.6    986.5    985.9  18.1     18.4     18.0  95.0     0.0      0.3           240.0             1.6  NaN      NaN      
1     A.01        N4033       岑溪马路昙容  22.93  110.75   91.0  2024/04/03 16     NaN      NaN      NaN      NaN  25.1     26.2     25.1   NaN     0.0      NaN             NaN             NaN  NaN      NaN      
2     A.01        N6252         平果马头  23.32  107.59  108.8  2024/04/03 16   992.4      NaN    992.4    992.0  28.4     29.1     28.4  75.0     0.0      NaN           151.0             4.6  NaN      NaN        
3     A.01        N5853       平南平南街道  23.55  110.39   32.5  2024/04/03 16  1003.0   1006.7   1003.6   1003.0  28.3     28.8     28.3  78.0     0.0      0.0           122.0             3.0  NaN      NaN      
4     A.01        N2394          融水镇  25.08  109.25  122.7  2024/04/03 16   995.2   1009.4    995.2    994.5  19.8     19.8     19.7  84.0     0.0      6.7            38.0             5.6  NaN      NaN
...    ...          ...          ...    ...     ...    ...            ...     ...      ...      ...      ...   ...      ...      ...   ...     ...      ...             ...             ...  ...      ...
3102  A.01        N7018           浦寨  21.99  106.69  250.0  2024/04/03 16     NaN      NaN      NaN      NaN  26.7     27.1     26.7   NaN     0.0      NaN             NaN             NaN  NaN      NaN
3103  A.01        N6127       凌云逻楼安水  24.36  106.72  875.0  2024/04/03 16     NaN      NaN      NaN      NaN  24.6     25.2     24.5   NaN     0.0      NaN             NaN             NaN  NaN      NaN      
3104  A.01        N1136         中和贵德  22.64  108.75  117.0  2024/04/03 16   992.2   1005.6    992.2    992.0  24.5     25.7     24.5  93.0     0.0      0.0           125.0             2.8  NaN      NaN        
3105  A.01        N2025           大坡  25.15  109.52  180.0  2024/04/03 16     NaN      NaN      NaN      NaN   NaN      NaN      NaN   NaN     0.0      NaN             NaN             NaN  NaN      NaN
3106  A.01        N8258           百乐  24.61  107.08  851.0  2024/04/03 16   911.9      NaN    911.9    911.3  22.5     23.5     22.5  78.0     0.0      NaN            38.0             8.6  NaN      NaN

④导出为csv
我们使用①内a的数据:

  1. import pandas as pd
  2. df = pd.DataFrame(a)
  3. df.to_csv('114514.csv')
复制代码


此时a的数据就被写入了csv文件内

⑤导出为excel
  1. import pandas as pd
  2. df = pd.DataFrame(a)
  3. df.to_excel('114514.xlsx',sheet_name='Sheet1')
复制代码

当然,也可以不加sheet_name=...,会自动新建工作簿并导入数据


(2)pandas处理数据
①拼接和追加
Concat:将 dataframe 拼接在一起(可按 rows 或 columns)。
Merge:类似于 SQL 中 Join 的用法。
Append:将数据按 rows 拼接到 dataframe 中。

Concat:
  1. import pandas as pd
  2. import numpy as np
  3. df=pd.DataFrame(np.random.randn(10,4))
  4. df1 = df[:3]
  5. print(df1)
  6. df2 = df[3:7]
  7. print(df2)
  8. df3 = df[7:]
  9. print(df3)
  10. df4 = pd.concat([df1,df2,df3],axis=0) #拼接
  11. print(df4)
复制代码

结果:

Merge:
  1. import pandas as pd

  2. left=pd.DataFrame({'key':['city','temp'],'value':['济南',26]})
  3. right=pd.DataFrame({'key':['city','temp'],'value':['兰州',17]})

  4. df = pd.merge(left,right,on='key')#根据 key 进行连接
  5. print(df)
复制代码

结果:
    key value_x value_y   
0  city      济南      兰州
1  temp      26      17   

Append:
  1. df=pd.DataFrame(np.random.randn(8,4),columns=['A','B','C','D'] ,index=range(1,9))
  2. s=df.iloc[0] #提取第一行数据
  3. df2 = df._append(s,ignore_index=False) #ignore_index 若为 Ture 则插入数据后索引将更新,否则保持原有索引值
  4. print(df2)
复制代码

结果:
          A         B         C         D
1 -0.545607 -1.674156  0.407157 -0.197993
2 -2.879381 -0.379466 -1.114840 -0.458665
3 -0.475737 -0.587428 -1.622563  0.435147
4  0.688105 -0.634619  0.274038  0.271619
5 -0.999742 -1.958650 -0.446780  0.858811
6 -0.504541 -1.107137 -0.834836 -0.569136
7  0.964024 -1.140281  0.711705  0.716114
8 -0.481429  0.421924  1.125234 -0.099209
1 -0.545607 -1.674156  0.407157 -0.197993

第一行复制出来之后被拼接到了最后一行
csv、excel等文件读取后也可按照上面的方法进行拼接。

②检索数据
  1. import pandas as pd

  2. df = pd.read_excel("hainan-2024040316.xlsx")

  3. #直接切片获取数据(行根据位置,列根据列名)
  4. df1 = df['Station_Id_C'] #根据属性名,获取列
  5. df2 = df[0:3] #切片获取位置(0:2)的数据,相当于 df.iloc[0:3]
  6. print(df1)
  7. print(df2)

  8. #利用 loc 根据标签值 Label 获取数据:可以交叉取值
  9. df3 = df.loc[0:3,['Station_Id_C','PRE_1h']] #获取索引值为(0:3)的中'Station_Id_C'的数据
  10. df4 = df.loc[1] #获取索引值为 2 的所有数据
  11. print(df3)
  12. print(df4)

  13. #利用 iloc 根据位置获取 Position 数据
  14. df5 = df.iloc[1] #获取第二行的所有数据
  15. df6 = df.iloc[1:3,[0,3]] #获取第二、三行,一、四列的数据
  16. print(df5)
  17. print(df6)

  18. #利用布尔值判断取数
  19. df7 = df[df['PRE_24h']>50] #提取出现24雨量大于50的站点数据
  20. print(df7)

  21. #isin()方法,类似于 SQL 中的 in 方法
  22. stidlist = ['57859','57927','57941','57942','57947','57948']
  23. df8 = df[df['Station_Id_C'].isin(stidlist)] #与 stidlist 中的所需站号匹配选取 df 中记录
  24. print(df8)
复制代码


结果太长了就不详细列出来了。



注意:大量数据情况下请使用csv,毕竟csv文件是一种专门的数据结构,读取同样的数据excel类型文件会比csv文件慢很多很多!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
头秃

2

主题

38

回帖

284

积分

热带低压

积分
284
 楼主| 发表于 2024-4-9 21:13 | 显示全部楼层
本帖最后由 bala 于 2024-4-9 22:39 编辑

接上期...
4.Xarray.Dataset

xarray 有两大数据类型:DataArray、Dataset。这里以使用较多的Dataset 为例。
Dataset 是 xarray 当中与 DataFrame 等价的多维数组。它是具有对齐维度的标签数组(DataArray 对象)的类似字典的容器。DataArray 只能存放单个量,而 DataSet 能够存放多个量。它被设计为 netCDF 文件格式的数据模型的内存表示。Dataset 有以下四个关键属性。·dims:存有维度名称的类字典映射(比如 {'x': 6, 'y': 6, 'time': 8})。·data_vars:与变量相关的类字典型容器,存放变量名称。·coords:用于标记变量使用的点(坐标,比如数字、时间对象、字符串)的类字典容器。·attrs:保存任意元数据(原始数据的属性)的字典,比如变量的名字、单位等。

(1)读取数据
我们可以通过 xarray.open_dataset()读取 Dataset 类型数据。对于netCDF数据传入文件名作为参数就能直接获得数据,对于GRIB 数据,需要添加引擎engine。
在本例的数据准备部分,使用了 xarray 的 open_dataset(filename_or_obj) 方法,在官方文档介绍中,这个方法默认只支持 netCDF3/4 格式的数据,但加入 engine 关键字(可选值{'netcdf4','scipy','pydap','h5netcdf','pynio','cfgrib','pseudonetcdf'})后,就会指定其他数据读取引擎,这里就指向了 cfgrib,cfgrib 再依靠eccodes 外部扩展库,实现对 grib2 文件的解析(生成gfs.pgrb2.0p25.f000.923a8.idx 索引文件,按照 idx 文件读取)

ECCODES GRIB教程中文版:https://perillaroc.github.io/eccodes-tutorial-cn/
Cfgrib:https://github.com/ecmwf/cfgrib
GFS数值:https://nomads.ncep.noaa.gov/
EC数值:https://data.ecmwf.int/forecasts/

我们下载后
  1. import xarray as xr

  2. file_path = 'F:/data_GFS/gfs.pgrb2.0p25.f000'
  3. tdata = xr.open_dataset(file_path, engine='cfgrib',backend_kwargs={'filter_by_keys': {'typeOfLevel': 'heightAboveGround', 'level': 2}})
  4. wdata = xr.open_dataset(file_path, engine='cfgrib',backend_kwargs={'filter_by_keys': {'typeOfLevel': 'heightAboveGround', 'level': 10}})
  5. mdata = xr.open_dataset(file_path, engine='cfgrib',backend_kwargs={'filter_by_keys': {'typeOfLevel': 'meanSea'}})
  6. upper = xr.open_dataset(file_path, engine='cfgrib',backend_kwargs={'filter_by_keys': {'typeOfLevel': 'isobaricInhPa'}})

  7. print(tdata)
  8. print(upper)
复制代码


tdata为地面数据内的2m气温,输出结果为:
<xarray.Dataset> Size: 8MB
Dimensions:            (latitude: 721, longitude: 1440)
Coordinates:
    time               datetime64[ns] 8B ...
    step               timedelta64[ns] 8B ...
    heightAboveGround  float64 8B ...
  * latitude           (latitude) float64 6kB -90.0 -89.75 -89.5 ... 89.75 90.0
  * longitude          (longitude) float64 12kB 0.0 0.25 0.5 ... 359.5 359.8   
    valid_time         datetime64[ns] 8B ...
Data variables:
    t2m                (latitude, longitude) float32 4MB ...
    sh2                (latitude, longitude) float32 4MB ...
Attributes:
    GRIB_edition:            2
    GRIB_centre:             kwbc
    GRIB_centreDescription:  US National Weather Service - NCEP
    GRIB_subCentre:          0
    Conventions:             CF-1.7
    institution:             US National Weather Service - NCEP
    history:                 2024-04-09T20:36 GRIB to CDM+CF via cfgrib-0.9.1...


upper为高空数据,输出结果为:
<xarray.Dataset> Size: 270MB
Dimensions:        (isobaricInhPa: 13, latitude: 721, longitude: 1440)
Coordinates:
    time           datetime64[ns] 8B ...
    step           timedelta64[ns] 8B ...
  * isobaricInhPa  (isobaricInhPa) float64 104B 1e+03 925.0 850.0 ... 100.0 50.0
  * latitude       (latitude) float64 6kB -90.0 -89.75 -89.5 ... 89.5 89.75 90.0
  * longitude      (longitude) float64 12kB 0.0 0.25 0.5 ... 359.2 359.5 359.8  
    valid_time     datetime64[ns] 8B ...
Data variables:
    gh             (isobaricInhPa, latitude, longitude) float32 54MB ...
    t              (isobaricInhPa, latitude, longitude) float32 54MB ...
    q              (isobaricInhPa, latitude, longitude) float32 54MB ...
    u              (isobaricInhPa, latitude, longitude) float32 54MB ...
    v              (isobaricInhPa, latitude, longitude) float32 54MB ...
Attributes:
    GRIB_edition:            2
    GRIB_centre:             kwbc
    GRIB_centreDescription:  US National Weather Service - NCEP
    GRIB_subCentre:          0
    Conventions:             CF-1.7
    institution:             US National Weather Service - NCEP
    history:                 2024-04-09T20:38 GRIB to CDM+CF via cfgrib-0.9.1...


高空数据输出的结果内还有几个物理量,我们可以继续print出来:
  1. print(upper.t)
复制代码
<xarray.DataArray 't' (isobaricInhPa: 13, latitude: 721, longitude: 1440)> Size: 54MB
[13497120 values with dtype=float32]
Coordinates:
    time           datetime64[ns] 8B ...
    step           timedelta64[ns] 8B ...
  * isobaricInhPa  (isobaricInhPa) float64 104B 1e+03 925.0 850.0 ... 100.0 50.0
  * latitude       (latitude) float64 6kB -90.0 -89.75 -89.5 ... 89.5 89.75 90.0
  * longitude      (longitude) float64 12kB 0.0 0.25 0.5 ... 359.2 359.5 359.8
    valid_time     datetime64[ns] 8B ...
Attributes: (12/29)
    GRIB_paramId:                             130
    GRIB_dataType:                            fc
    GRIB_numberOfPoints:                      1038240
    GRIB_typeOfLevel:                         isobaricInhPa
    GRIB_stepUnits:                           1
    GRIB_stepType:                            instant
    ...                                       ...
    GRIB_name:                                Temperature
    GRIB_shortName:                           t
    GRIB_units:                               K
    long_name:                                Temperature
    units:                                    K
    standard_name:                            air_temperature


假如数据中含有一个名为 var 的物理量,我们可以通过 ds.var 或 ds[var]来获取对应的Dataset对象,比如 ds.t、ds[‘t’]、ds.variables[‘t’],实际取值的时候需要ds.var.data或者ds.var[:]。可以看到温度一共有 13层,涵盖全球,分辨率为 0.25°。

(2)索引
Xarray 数据的索引方法:

  1. upper['t'].isel(isobaricInhPa=5, longitude=120, latitude=40).data#计算500hPa 120°E 40°N的气温
  2. upper['t'].isel(isobaricInhPa=9, longitude=120,latitude=slice(20,40)).mean(dim= 'latitude')#计算 500hPa 沿 120°E 经线,从 20°N 到40°N 之间温度的平均值
复制代码

上面两个结果:
253.3999

<xarray.DataArray 't' ()> Size: 4B
array(230.60002, dtype=float32)
Coordinates:
    time           datetime64[ns] 8B ...
    step           timedelta64[ns] 8B ...
    isobaricInhPa  float64 8B 500.0
    longitude      float64 8B 30.0
    valid_time     datetime64[ns] 8B ...


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
头秃

2

主题

38

回帖

284

积分

热带低压

积分
284
 楼主| 发表于 2024-4-9 21:28 | 显示全部楼层
本帖最后由 bala 于 2024-5-3 21:54 编辑

第七章 Matplotlib---Python绘图核心

1. Matplotlib 可视化工作原理

matplotlib官方链接:https://matplotlib.org/
建议英语能力好的直接阅读官方文档,英语不好的看我门下面的汉化(bushi)

(1)API
  Matplotlib 提供以下三个层面的接口 API,共同协作实现数据的可视化:
1.matplotlib.backend_bases.FigureCanvas:画布,即图表的绘制区域。
2.matplotlib.backend_bases.Renderer:渲染器,知道如何在画布上绘图。
3.matplotlib.artist.Artist:图元,知道如何使用渲染器在画布上进行操作。
三者的逻辑关系和打印文档过程类似:画布就像打印纸(A4 大小、白色);渲染器就好比打印机中的核心部件(墨盒、喷墨打印头);操作图元就像最后的一系列人工操作(码字-排版-打印操作-打印属性设置-确认打印)。最终会把使用者需要的文字、图像打印在纸上。最后一步是使用者接触最多的,而前两者的工作原理、设备构造等细节则不需要过分关心。

(2)Artist 图元
Matplotlib 绘制图形中的任何信息都作为 Artist 对象的实例,每个图元都有很多可设置的显示属性。Figure 实例本身就包含一个和 Figure 同样大小的 Rectangle(Figure.patch),可以用它设定 Figure 背景色、透明度。同样,Axes 的框盒(Axes.patch)也可以设定颜色、透明度以及其他属性。Patch 从 MATLAB 继承而来,一个二维同一颜色区域。所有的 Matplolib Artist 都有表中所列的特性。常见的容器类图元有 Figure 画布、Axes 绘图区、Axis 坐标轴、Tick 刻度等.
alpha 透明度,取值范围 0-1,0 为全透明,1 为完全不透明
animated 布尔型,在绘制动画时使用
axes Artist 存在的 Axes 实例,可能没有
clip_box Artist 的裁切框
clip_on 是否裁切
clip_path 裁切多边形,由 matplotlib.path 操作
contains 测试 Artist 是否包含选取点的函数
figure Artist 存在的 Figure 实例,可能没有
label 标签
picker 控制对象选取的对象
transform 转换
visible 布尔型,Artist 是否被绘制(显示)
zorder 确定绘图顺序的数字
rasterized 布尔型,把矢量转换为栅格图像(为了压缩或 EOS 透明度)

①Figure画布
Figure 是最高层次的容器(本身也是图元),也命名为“画布”,包含了整幅图像的所有图元。它首先包含了一个矩形框范围(使用 IDLE 绘制图像,Figure 作为绘图窗口存在,也可以认为这个窗口是 FigureConvas,内部主窗区是画布),作为盛放其他图元的容器。这个矩形框 Rectangle 是一个 Figure.patch 子类的实例。
  1. import matplotlib.pyplot as plt
  2. fig=plt.figure()
  3. print(fig)
  4. plt.show()
复制代码

如图,首先你会发现会弹出一个窗口,并且代码的输出栏你会发现输出了一个尺寸
  1. Figure(640x480)
复制代码

这个空白区域就是Figure画布,因为我们能没有执行任何其他的东西,所以是空白的。
我们可以在这个画布内添加一个或多个子图 Subplot、绘图区 Axes。例如创建的子图 ax1,它是对象 matplotlib.axes._subplots.AxesSubplot的一个实例。它包含了四条坐标脊线 Spine、两条坐标轴(XAxis 和 YAxis)、三个文本实例 Text 和一个矩形框盒 Rectangle。通过 add_axes()方法添加的 matplotlib.axes._axes.Axes 类型的 axes 同样有这些子图元。此时,再使用fig.get_children()方法查看,会发现多了 ax1 和 ax2 两个子图元。如果只想查询在最高级别的容器 fig 中绘图区类型的图元,可以通过fig.axes 查看绘图区列表。由于 Figure 保留了“Current axes”的概念,以支持 pyplot 状态机制,最好不要直接从 axes 列表中插入或删除,最好用 add_subplot()、add_axes()添加,用 delaxes()删除。
我们看一下官方的栗子:
  1. import matplotlib.pyplot as plt
  2. fig = plt.figure()
  3. fig.add_subplot(231)
  4. ax1 = fig.add_subplot(2, 3, 1)  #与上面功能相同
  5. fig.add_subplot(233, projection='polar')  #极坐标图
  6. fig.add_subplot(234, sharex=ax1)  #共享ax1的x坐标轴
  7. fig.add_subplot(235, facecolor="red")  #红色底图
  8. plt.show()
复制代码

输出结果如图:

Figure 画布对象可以包含以下图元对象:
patch : 作为背景的 Rectangle 对象。创建即包含与 figure 大小相同的矩形框。
axes : Axes 对象列表。通过 add 方法添加,如未先添加直接绘图,则默认创建一个。
images : FigureImage 对象列表,用来显示图片。
egends : Legend 对象列表,显示这个画布中的所有信息的图例。
lines : Line2D 对象列表。
patches : patch 对象列表。例如多边形、矩形框等。
texts : Text 对象列表,用来显示文字。标题 suptitle 最终也创建一个Text 对象。

②axes绘图区
matplotlib.axes.Axes 类是整个 Matplotlib“宇宙”的核心,是 Matplotlib中最重要的类,也是使用最多的类。它可以容纳绝大多数的 Artist 图元。
“Axes”直译是坐标轴的复数形式,数据可视化得到的图形包含两条或多条坐标轴,这些坐标轴围成的区域中才是图形。这里将之命名为“绘图区”,一方面因为读者要看到的图形(折线、条形、等值线等)在这个容器中:Axes提供了很多辅助方法(plot()、text()、hist()、imshow())用以创建原型图类图元、修改其设置等等(表 4-3),当需要时绘制显示他们。另一方面外围的一些辅助信息(坐标轴、刻度等)也在这个容器中:Axes 同样有辅助方法(set_*())可以配置或修改 x-axis、tick、ticklabel、axislabel 的属性。Axes 可以在 Figure 任何地方创建(figure.add_axes());由 Subplot 实例采用行列规则划分创建的 Subplot 其实是 Axes 的一个特例(子类/衍生类)。用 add_subplot 添加的是 matplotlib.axes._subplots.AxesSubplot;用 add_axes 添加的是 matplotlib.axes._axes.Axes。上面的代码可以看到 ax1 或者 ax2,和 figure 类似,绘图区实例首先默认包含了一个 Patch 类型的矩形框盒 Rectangle,对应笛卡尔直角坐标系的矩形框(如果是极坐标系,则是圆形 Circle),它决定了绘图区域大小、形状、背景色、边框。其次有 spines 和 Axis 共同构成的数学意义上的坐标系统。
多的概念啥的也就不再说了。

③axis坐标轴
Axis 容器包括坐标轴上的 Tick 实例和坐标轴标题 label。Tick 也是一个容器,包含刻度线 tickline、刻度标签 ticklabel、和坐标网格线 gridline。刻度包括主要刻度和次要刻度,分别通过 Axis.get_major_ticks()和 Axis.get_minor_ticks()方法获得。每个刻度线都是一个 XTick 或者 YTick 对象,它包括实际的刻度线和刻度标签。为了方便访问刻度线和标签,Axis 对象提供了 get_ticklabels()和 get_ticklines()方法分别直接获得刻度线和刻度文本。

小总结:画布、绘图区、坐标轴等图元关系示意如下图

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
头秃

1

主题

16

回帖

342

积分

论坛版主-副热带高压

积分
342
发表于 2024-4-10 07:28 | 显示全部楼层
非常好的分享
在这里额外多说一句,隔壁的气象家园论坛上有更多的气象编程经验帖,大家也可以去那里面看一下
当一切都被寒潮撕成碎片的时候,只有西风在阿留申南岸吟唱着永恒的悲歌。

0

主题

14

回帖

419

积分

热带低压

积分
419
发表于 2024-4-11 16:22 | 显示全部楼层
进来学习。
如果读写中有中文字符,写入的时候有的机器有可能遇到乱码。在to_csv里面中添加编码设定例如encoding='UTF-8'会稳妥一点。

点评

感谢,已加入到教程  发表于 2024-4-20 14:56

2

主题

38

回帖

284

积分

热带低压

积分
284
 楼主| 发表于 2024-5-3 21:55 | 显示全部楼层
本帖最后由 bala 于 2024-5-3 22:17 编辑

......接上一章
2. Matplotlib 折线图
(1)先画一个最简单的斜直线
  1. import matplotlib.pyplot as plt       
  2. x = [0,2] #x等于0、2
  3. y = [0,2] #对应的y等于0、2
  4. plt.plot(x,y) #画线
  5. plt.show()        #显示图形
复制代码

如图所示:


画一个y=x²
  1. import matplotlib.pyplot as plt
  2. import numpy as np
  3. import math

  4. x = np.arange(-10, 11, 1)        #从-10到10,间隔1取
  5. plt.plot(x,[math.pow(i,2) for i in x]) #y=x²
  6. plt.show()
复制代码

注意,我们用到了math库,math库是一个非常重要的库,后面在实况、探空、数值等填图都会使用此库。详细使用方法参考https://www.runoob.com/python3/python-math.html

(2)折线图样式
对于折线图有线色、线型、线宽、标记、线名等参数可进行自定义属性设置。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
头秃

12

主题

598

回帖

1537

积分

强热带风暴

积分
1537
发表于 2024-5-27 23:07 | 显示全部楼层
bala 发表于 2024-4-6 19:59
第二章 开发环境推荐

开发环境意思就是你要在哪个地方写代码。下面介绍几种集成开发环境:

vscode有一些麻烦的问题
一些基础的图,比如matplotlib、turtle库画图很容易运行出来。但是如果是气象图这种内容比较多的,就出不了图,另一个用vscode的用户也出现了出不了图的问题,我运行ec预报图,代码没有问题(有问题在运行前就会自动报错),结果却出现这个
RuntimeError: cannot find the eccodes library

pycharm好像就没有这些问题
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|TY_Board论坛

GMT+8, 2024-12-4 01:24 , Processed in 0.038128 second(s), 19 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表