【问题标题】:apply function over all months xarray python在所有月份应用函数xarray python
【发布时间】:2019-06-09 00:45:28
【问题描述】:

在感兴趣的 xarray 月份有效地应用函数

import pandas as pd
import numpy as np
import xarray as xr

time = pd.date_range('2010-01-01','2018-12-31',freq='M')
lat = np.linspace(-5.175003, -4.7250023, 10)
lon = np.linspace(33.524994, 33.97499, 10)
precip = np.random.normal(0, 1, size=(len(time), len(lat), len(lon)))

ds = xr.Dataset(
    {'precip': (['time', 'lat', 'lon'], precip)},
    coords={
        'lon': lon,
        'lat': lat,
        'time': time,
    }
)

Out[]:
<xarray.Dataset>
Dimensions:  (lat: 10, lon: 10, time: 108)
Coordinates:
  * lon      (lon) float64 33.52 33.57 33.62 33.67 ... 33.82 33.87 33.92 33.97
  * lat      (lat) float64 -5.175 -5.125 -5.075 -5.025 ... -4.825 -4.775 -4.725
  * time     (time) datetime64[ns] 2010-01-31 2010-02-28 ... 2018-12-31
Data variables:
    precip   (time, lat, lon) float64 -0.7862 -0.28 1.236 ... 0.6622 -0.7682

我目前的做法

我目前通过以下方式应用功能:

  • 循环遍历所有月份
  • 选择该月原始数据集中的所有时间步长
  • 对这些月份应用一个函数(这里是标准化排名)
  • 将每月DataArrays 列表重新组合成一个包含所有时间步长的Dataset

该函数可能与气候学有所不同,但这里是归一化等级。 - 获取变量值与数据集中该 month 的所有其他值相比的排名 - 将其设置在0-100的范围内

variable = 'precip'
rank_norm_list = []

# loop through all the months
for mth in range(1, 13):
    # select that month
    ds_mth = (
        ds
        .where(ds['time.month'] == mth)
        .dropna(dim='time', how='all')
    )
    # apply the function to that month (here a normalised rank (0-100))
    rank_norm_mth = (
        (ds_mth.rank(dim='time') - 1) / (ds_mth.time.size - 1.0) * 100.0
    )
    rank_norm_mth = rank_norm_mth.rename({variable: 'rank_norm'})
    rank_norm_list.append(rank_norm_mth)

# after the loop re-combine the DataArrays
rank_norm = xr.merge(rank_norm_list).sortby('time')

Out[]:
<xarray.Dataset>
Dimensions:    (lat: 10, lon: 10, time: 108)
Coordinates:
  * time       (time) datetime64[ns] 2010-01-31 2010-02-28 ... 2018-12-31
  * lat        (lat) float64 -5.175 -5.125 -5.075 ... -4.825 -4.775 -4.725
  * lon        (lon) float64 33.52 33.57 33.62 33.67 ... 33.82 33.87 33.92 33.97
Data variables:
    rank_norm  (time, lat, lon) float64 75.0 75.0 12.5 100.0 ... 87.5 0.0 25.0

有没有不涉及循环和选择的聪明/更有效的方法?

【问题讨论】:

    标签: python python-3.x python-xarray


    【解决方案1】:

    感谢您提供的好例子。确实有一种更简单的方法可以使用groupby and apply

    def rank_norm(ds, dim):
        return (ds.rank(dim=dim) - 1) / (ds.sizes[dim] - 1.0) * 100.0
    
    result = ds.groupby('time.month').apply(rank_norm, args=('time',))
    

    【讨论】:

    • 感谢@spencerkclark!这真的很有帮助。在无耻的呼救声中,您知道如何从组(即十分位)中分配 bin 标签。我问的 SO 问题是here
    • 没问题!我试了一下;让我知道我是否在正确的轨道上。如果需要,我很乐意修改答案。
    猜你喜欢
    • 2019-09-23
    • 2021-02-01
    • 2021-12-28
    • 2020-07-02
    • 1970-01-01
    • 2018-04-06
    • 2020-06-19
    • 2017-07-19
    • 2017-07-31
    相关资源
    最近更新 更多