如何将xarray DataArray中存在于指定列表的值标记为1,其余为0?
解决思路:生成匹配指定列表的xarray二进制数组
问题背景
我有一个非零数值列表blob_numbers_126_list,需要与三维(time,lat,lon)的xarray DataArray blobs_126对比,生成二进制数组——值在列表中则标记为1,否则为0。
列表生成代码:
blob_numbers_126 = blobs_126.where(icemask_126_regrid[30,:,:] == 1).data.flatten() blob_numbers_126 = blob_numbers_126[~np.isnan(blob_numbers_126)] blob_numbers_126_list = list(set(blob_numbers_126[blob_numbers_126!=0]))
当前使用xr.where()的代码得到全1数组,不符合预期:
blobs_126_source = blobs_126.where(blobs_126[:,:,:].data == any(np.array(blob_numbers_126_list)),1,0)
错误原因
any(np.array(blob_numbers_126_list))会将整个列表转换为单个布尔值(只要列表非空就返回True),导致条件变为blobs_126.data == True,所有非零数值都会匹配该条件,最终生成全1数组。- 直接操作
.data绕过了xarray的维度对齐机制,不是推荐的用法。
正确解决方法
方法1:使用xarray内置isin()方法(推荐)
xarray的DataArray自带isin()方法,可直接逐元素检查是否在目标列表中,返回布尔掩码后转换为1/0数组:
# 生成布尔掩码 match_mask = blobs_126.isin(blob_numbers_126_list) # 转换为二进制数组,保留原维度和坐标 blobs_126_source = match_mask.astype(int) # 也可以用xr.where实现相同效果 blobs_126_source = xr.where(match_mask, 1, 0)
方法2:结合numpy的in1d()操作
如果习惯用numpy处理,可先展平数组检查匹配,再重构回原三维结构:
# 展平数组并检查每个元素是否在列表中 flat_match = np.in1d(blobs_126.data.flatten(), blob_numbers_126_list) # 重构回原DataArray的形状 match_mask = flat_match.reshape(blobs_126.shape) # 转换为带坐标的DataArray blobs_126_source = xr.DataArray(match_mask.astype(int), coords=blobs_126.coords, dims=blobs_126.dims)
额外优化:用集合提升匹配效率
由于你的列表是通过set生成的,直接使用集合做匹配能大幅提升效率(尤其当元素数量较多时):
# 直接生成集合而非列表 blob_numbers_126_set = set(blob_numbers_126[blob_numbers_126!=0]) # 后续用isin(blob_numbers_126_set)即可,xarray会自动兼容集合类型
内容的提问来源于stack exchange,提问作者jpleis
相关产品推荐
相关产品推荐

