如何优雅地用字典dict映射numpy array:map和np.vectorize

本文介绍了如何使用map函数和numpy的vectorize函数将numpy一维和多维数组根据字典进行映射,提供了一种简洁的解决方案。通过示例展示了如何将字符数组转换为对应的数值数组,适用于一维和多维数组的处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

如何优雅地用字典dict映射numpy array:map和np.vectorize

问题

现在有一个ndarray和字典dict如下:

a1 = np.array(['a', 'b'])
d = {'a':1, 'b':2}

想根据字典d中的对应关系将a1映射成如下:

array([1, 2])

方案一:map函数映射一维ndarray

第一反应是使用map函数,不过其中需要注意的是,map中传入的函数部分需为dict.get

a1 = np.array(['a', 'b'])
d = {'a':1, 'b':2}
a2 = np.array(list(map(d.get, a1)))
a2
>>> array([1, 2])

如上,一行代码就解决了,缺点是只可以用在一维ndarray上。

方案二:np.vectorize映射多维ndarray

对于多维ndarray,可以使用numpyvectorzie函数。

a1 = np.array([['a', 'b'], ['b', 'a']])
d = {'a':1, 'b':2}
a2 = np.vectorize(d.get)(a1)
a2
>>> array([[1, 2],
       [2, 1]])

依旧一行代码解决问题,优雅!

import xarray as xr import numpy as np from scipy.stats import gamma from scipy.special import erfinv import warnings warnings.filterwarnings('ignore') #%% 基础配置 input_path = r'D:\heatwave\data\precip\precip_merged.nc' output_dir = r'D:\heatwave\data\precip' lat_range = [15, 55] lon_range = [105, 140] #%% 步骤1:增强型数据预处理(保持不变) def preprocess_data(): ds = xr.open_dataset(input_path) # 统一维度命名 rename_dict = {} if 'latitude' in ds.dims: rename_dict['latitude'] = 'lat' if 'longitude' in ds.dims: rename_dict['longitude'] = 'lon' ds = ds.rename(rename_dict) # 空间裁剪 ds_china = ds.sel(lat=slice(*lat_range), lon=slice(*lon_range)) # 移除闰日 ds_china = ds_china.sel(time=~((ds_china['time.month'] == 2) & (ds_china['time.day'] == 29))) return ds_china #%% 步骤2:修正后的SPI-30计算(关键修改) def calculate_spi30(precip): # 30天累积降水 precip_roll = precip.rolling(time=30, min_periods=30, center=False).sum() # 增强Gamma拟合函数 def gamma_fit(data): valid_data = data[~np.isnan(data)] if len(valid_data) < 5 or np.all(valid_data == 0): return (np.nan, 0, 0) try: return gamma.fit(valid_data + 1e-6, floc=0) except: return (np.nan, 0, 0) # 关键修改:预处理每个dayofyear的参数 grouped = precip_roll.groupby('time.dayofyear') params = grouped.map(lambda x: gamma_fit(x.values)) # 创建参数数据集 params_ds = xr.Dataset({ 'a': (['dayofyear'], params[:, 0]), 'loc': (['dayofyear'], params[:, 1]), 'scale': (['dayofyear'], params[:, 2]) }, coords={'dayofyear': params.dayofyear}) # 核心计算逻辑 def calculate_gamma_cdf(data, doy): a = params_ds['a'].sel(dayofyear=doy).item() scale = params_ds['scale'].sel(dayofyear=doy).item() return gamma.cdf(data, a=a, loc=0, scale=scale) # 应用计算 spi30 = xr.apply_ufunc( calculate_gamma_cdf, precip_roll, precip_roll['time.dayofyear'], input_core_dims=[[], []], output_core_dims=[[]], vectorize=True, dask='parallelized', output_dtypes=[float] ) # 转换为标准正态分布 spi30 = xr.apply_ufunc( lambda x: np.sqrt(2)*erfinv(2*x-1) if not np.isnan(x) else np.nan, spi30, dask='parallelized', output_dtypes=[float] ) return spi30.rename('SPI30').transpose('time', 'lat', 'lon') #%% 步骤3:主处理流程(保持不变) def main_process(): ds = preprocess_data() spi30 = calculate_spi30(ds['precip']) # 编码设置 encoding = { 'SPI30': {'zlib': True, 'complevel': 1, 'dtype': 'float32'}, 'lat': {'dtype': 'float32'}, 'lon': {'dtype': 'float32'}, 'time': {'dtype': 'int32', 'units': 'days since 1900-01-01'} } # 输出文件 spi30.to_netcdf( f'{output_dir}/SPI30_daily.nc', encoding=encoding, unlimited_dims=['time'] ) print(f"处理完成!维度验证:{spi30.dims}") #%% 执行 if __name__ == '__main__': main_process()对以上代码报错了'tuple' object has no attribute 'dims',帮我解决并生成完整代码
最新发布
03-24
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值