Python气象数据处理进阶之Xarray(2):如何优雅的索引数据

在了解了数据的结构之后,我们便可以开始着手处理数据了,那么如何才能从一个数据或数据集中拿到我们所需要的那部分数据呢?
Xarray官方提供了三种方法用来索引数据:
1.利用下标索引(index)
2.利用坐标值索引(coords)
3.利用标签索引(labels)
我对官方的表格实例做了修改,更符合我们气象专业的理解。



da指DataArray;ds指Dataset
虽然说给出了多种索引数据的方法,但是实际上通常用到的只有前两种。
具体通过一些例子来表现(均是由官方文档例子修改得到,为了更符合气象数据的结构):这建立了一个2000年1月1号-1月4号,且有三个纬度层

da = xr.DataArray(np.random.rand(4, 3),[('time', pd.date_range('2000-01-01', periods=4)),('lat', [30, 60, 90])])

索引方法

下边是各种花样索引:

ex1
print(da[:2])
#<xarray.DataArray (time: 2, lat: 3)>
#array([[0.64658774, 0.25076033, 0.7425908 ],
#       [0.40127745, 0.08413761, 0.55898847]])
#Coordinates:
#  * time     (time) datetime64[ns] 2000-01-01 2000-01-02
#  * lat      (lat) int64 30 60 90

可以看到这样的结果相当于da[0:2,:],纬度维相当于被省略了,这种形式也是python的特色,而不是xarray独有的。

ex2
print(da[:, [2, 1]])
#<xarray.DataArray (time: 4, lat: 2)>
#array([[0.7425908 , 0.25076033],
#       [0.55898847, 0.08413761],
#       [0.82131977, 0.52965844],
#       [0.02323461, 0.80289017]])
#Coordinates:
#  * time     (time) datetime64[ns] 2000-01-01 2000-01-02 2000-01-03 2000-01-04
#  * lat      (lat) int64 90 60

注意看会发现纬度维的顺序变了,实际上da[:,::-1]的操作会更实用,因为不同的资料纬度排列不同,有的是从南到北,有的是从北到南,可以通过::-1来实现颠倒。

ex3
print(da.loc['2000-01-01':'2000-01-02', 90])
#<xarray.DataArray (time: 2)>
#array([0.7425908 , 0.55898847])
#Coordinates:
#  * time     (time) datetime64[ns] 2000-01-01 2000-01-02
#    lat      int64 90

通过.loc的方式定位标签,这种方法太实用了!比如说要选取区域数据,

a.loc['time1':'time2',lat1:lat2,lon1:lon2]

顺便说,索引出来的数据是直接可以修改或者计算的

da.loc['2000-01-01', [90, 60]] = -10
print(da)
#<xarray.DataArray (time: 4, lat: 3)>
#array([[  0.64658774, -10.        , -10.        ],
#       [  0.40127745,   0.08413761,   0.55898847],
#       [  0.48245825,   0.52965844,   0.82131977],
#       [  0.69295939,   0.80289017,   0.02323461]])
#Coordinates:
#  * time     (time) datetime64[ns] 2000-01-01 2000-01-02 2000-01-03 2000-01-04
#  * lat      (lat) int64 30 60 90

PS:关于后两种的.sel和.isel的使用,我觉得十分鸡肋,也可能我没抓住精髓,感兴趣的可以参考官方文档,我不在此展开了,浪费大家阅读时间。

有时候,我们无法精准确定我们的需求或者其他特殊的需要,这时候要使用到模糊索引。
同样的,我们新建一个简单的da(以下da均代表DataArray)

da = xr.DataArray([1, 2, 3], [('lat', [30, 60, 90])])
print(da)
#<xarray.DataArray (lat: 3)>
#array([1, 2, 3])
#Coordinates:
#  * lat      (lat) int64 30 60 90
ex4
print(da.sel(lat=[30.5, 60.9], method='nearest'))
#<xarray.DataArray (lat: 2)>
#array([1, 2])
#Coordinates:
#  * lat      (lat) int64 30 60
print(da.sel(lat=30.1, method='backfill'))
#<xarray.DataArray ()>
#array(2)
#Coordinates:
#    lat      int64 60

通过参数method='nearest'索引到了离30.5和60.9最近的纬度的数据
通过参数method='backfill'索引到了大于30.1的最近的纬度的数据

ex5
print(da.reindex(lat=[25,30,35,60,65,85,90,95], method='pad'))
#<xarray.DataArray (lat: 8)>
#array([nan,  1.,  1.,  2.,  2.,  2.,  3.,  3.])
#Coordinates:
#  * lat      (lat) int64 25 30 35 60 65 85 90 95

通过参数method='pad'展开得到了指定纬度的数据,这里用插值的说法不太合适,因为并没有插值,只是就近相等的原则。插值有具体的函数,我会在后边的文章中详细介绍。

ex6
print(da.reindex(lat=[32,35], method='nearest', tolerance=2))

通过 tolerance=2参数的设置,指定模糊索引的边界限制。

以上是对DataArray的索引方式,基本上对于Dataset的操作也大致相等,实际上在使用过程中对Dataset的直接操作是比较少的,通常是先取出Dataset中的某变量(DataArray)然后再对变量进行各种切片和索引。

数组掩码(多用于缺测处理)

Xarray也提供了用于数组掩码的操作:

ex7
print(da.where(da.lat < 60))
#<xarray.DataArray (time: 4, lat: 3)>
#array([[0.41845339,        nan,        nan],
#       [0.82314399,        nan,        nan],
#       [0.46403574,        nan,        nan],
#       [0.90320489,        nan,        nan]])
#Coordinates:
#  * time     (time) datetime64[ns] 2000-01-01 2000-01-02 2000-01-03 2000-01-04
#  * lat      (lat) int64 30 60 90

通过where()语句,将不满足条件的位置全部设置为缺测,我举几个实用的方法:比如结合shp文件将研究区域外的数据缺测,或是剔除数据异常点的数据等等。

除了掩码外,还提供了一种直接剔除数据的办法:

ex8
print(da.where(da.lat < 60, drop=True))
#<xarray.DataArray (time: 4, lat: 1)>
#array([[0.41845339],
#       [0.82314399],
#       [0.46403574],
#       [0.90320489]])
#Coordinates:
#  * time     (time) datetime64[ns] 2000-01-01 2000-01-02 2000-01-03 2000-01-04
#  * lat      (lat) int64 30

可以看到,不满足条件的位置全部删掉了。个人感觉不太实用,这样改变了数组的shape,可能在后续的操作会遇到更多的麻烦。
根据自己需要选择合适方法即可。

子集索引

实在不知道该怎么描述,只好用子集索引来形容这种方法。实质就是自己定义一个范围,索引该范围之内的数据。

ex9
print(da.lat.isin([30,35]))
#<xarray.DataArray 'lat' (lat: 3)>
#array([ True, False, False])
#Coordinates:
#  * lat      (lat) int64 30 60 90

这种用法用的比较少,根据需要自己开发。
isin()函数同样支持drop=True参数的设置,效果同上。

官方文档还有更多的索引实例,也有一些更加复杂的,无非是上述几种索引方式的组合运用,如果熟悉了几种基本的索引方式后并理解了其中的原理的话,自己就能摸索出来那些复杂的组合运用,比如说从一个N年的逐日数据集中挑选每年某月某日到某月某日的数据,或者计算一个气候指数时,直接选出需要范围的数据,进行区域平均或者时间平均即可得到想要的结果。

个人感觉相比于NCL,Xarray为Python的数据索引提供了太多的便利,再结合上CDO对数据的预处理,可以让脚本的代码大大的简化,也减小了出错的机率,就运行速度而言,Xarray读取数据的速度是非常快的,内存限制也完全取决于计算机的最大内存,好评!

预告一下,下一节我会介绍Xarray中的数据插值功能。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 201,552评论 5 474
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,666评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,519评论 0 334
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,180评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,205评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,344评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,781评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,449评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,635评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,467评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,515评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,217评论 3 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,775评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,851评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,084评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,637评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,204评论 2 341

推荐阅读更多精彩内容