You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python嵌套for循环如何沿新维度存储NetCDF读取的多维数组

问题背景
  • 本人为Python初学者,此前有Matlab使用经验,目前正迁移到Python开展数据处理工作
  • 需求为通过for循环批量读取多个.nc(NetCDF)格式文件,沿新增的记录维度存储读取到的变量数据
  • 单次循环读取得到的变量j、j1维度均为4×30×30,需要遍历exp列表的3个元素,将获取到的j变量数据存入目标变量appn的第0维,最终得到维度为3×4×30×30的appn数组
  • 该操作在Matlab中实现逻辑简单,但在Python环境下暂未找到正确实现方式,自行编写的代码存在语法错误、维度不匹配问题
原错误代码
import os, sys
import netCDF4
from mpl_toolkits.basemap import Basemap
import numpy as np
import matplotlib.pyplot as plt
from cdo import *
import xarray as xr
cdo=Cdo()

indices = ["T"]
models = ["MJ", "MK", "ML"]
seasons =["JJA", "DJF"]
period =["base", "proj"]
exp = ["ssp1", "ssp2", "ssp3"]
odir = "/outs_pytry/season/"
top ="/outs_pytry/monmean_1/"
os.makedirs(odir, exist_ok=True)
#appn=[]
appnx=[]
#pr_arr = np.zeros([models,nlat,nlon], dtype='f4')
#pr_arr = np.zeros([], dtype='f4')
j=[]    
for m in models:
        folder = "%s"%(top)
        if m in ["ML"]:
            run = "r1i1p1f2"
        else:
            run = "r1i1p1f1"
        for i in indices:
                for e in exp:
                
                  origfi1 = '%s%s_%s_%s_%s_base.nc'%(folder,i, m, e, run)
                  origfi2 = '%s%s_%s_%s_%s_proj.nc'%(folder,i, m, e, run)
                                       
                    
                  k=cdo.timselmean(3,11,9, input="%s"%origfi1, output="%s%s_%s_%s_%s_DJF_proj.nc"%(odir,i,m,e,run), returnCdf=True)
                  k1=cdo.timselmean(3,5,9, input="%s"%origfi1, output="%s%s_%s_%s_%s_JJA_proj.nc"%(odir,i,m,e,run), returnCdf=True)
                           
                  j=k.variables["T"][:]
                  
                  j1=k1.variables["T"][:]
                  
    
                  lat=k.variables["lat"]
                  lon=k.variables["lon"]
    
                  #appn=np.zeros([3,4,lon,lat], dtype='f4')
                  datain = np.array(j)

                  #Confused with how to store data in appn , so that it has a fourth dimension of size 'e'?
                  appn(e,:,:,:) =datain
                  appn.append(datain)
错误原因
  1. 语法错误:Python中数组/列表索引使用方括号[],和Matlab用圆括号()的规则不同,原代码里appn(e,:,:,:) = datain本身不符合Python语法
  2. 逻辑错误:原代码把两种数组存储逻辑混写,既尝试类Matlab的预分配数组按索引赋值,又尝试列表追加,两种逻辑二选一即可实现需求
  3. 性能隐患:如果直接在循环里用np.append()拼接数组,每次拼接都会全量拷贝内存,数据量大时运行速度会极慢
实现方案

方案1:预分配numpy数组(和Matlab使用习惯一致)

适合提前明确最终数组维度的场景,内存连续运行效率高,和Matlab预分配内存的操作逻辑完全对齐:

  1. 在进入exp循环前,初始化维度匹配的零值数组,第一维长度为exp列表的长度3,后三维和单次读取的j维度保持一致为4×30×30
  2. 循环中增加索引计数器,每读取一个datain就写入数组对应索引的切片位置
    对应修正代码片段:
# ------------ 循环外初始化(放在exp循环外层即可)------------
appn = np.zeros([len(exp), 4, 30, 30], dtype='f4')
exp_idx = 0 # 标记当前写入的exp维度位置

# ------------ exp循环内逻辑 ------------
for e in exp:
    # 原有文件读取、cdo计算逻辑保留不变
    origfi1 = '%s%s_%s_%s_%s_base.nc'%(folder,i, m, e, run)
    origfi2 = '%s%s_%s_%s_%s_proj.nc'%(folder,i, m, e, run)
    k=cdo.timselmean(3,11,9, input="%s"%origfi1, output="%s%s_%s_%s_%s_DJF_proj.nc"%(odir,i,m,e,run), returnCdf=True)
    k1=cdo.timselmean(3,5,9, input="%s"%origfi1, output="%s%s_%s_%s_%s_JJA_proj.nc"%(odir,i,m,e,run), returnCdf=True)
    j=k.variables["T"][:]
    j1=k1.variables["T"][:]
    lat=k.variables["lat"]
    lon=k.variables["lon"]

    datain = np.array(j)
    # 注意索引使用方括号
    appn[exp_idx, :, :, :] = datain
    exp_idx += 1 # 索引后移,准备写入下一个exp的数据

循环结束后appn就是维度为3×4×30×30的目标数组。如果后续需要存储多模型、多指数的结果,只需要对应调整预分配数组的第一维长度即可。

方案2:列表暂存后一次性拼接

适合不确定最终数组长度的场景,不需要提前计算维度:

  1. 循环外初始化一个空列表
  2. 每次循环读取到datain后,直接追加到列表中
  3. 所有循环结束后,用np.stack()沿第0维拼接列表内的数组,直接得到目标维度的结果
    对应修正代码片段:
# ------------ 循环外初始化 ------------
appn_list = []

# ------------ exp循环内逻辑 ------------
for e in exp:
    # 原有文件读取、cdo计算逻辑保留不变
    # ... 省略重复的文件读取代码 ...
    datain = np.array(j)
    appn_list.append(datain)

# ------------ 循环结束后拼接数组 ------------
appn = np.stack(appn_list, axis=0)

拼接完成后appn的维度自动为3×4×30×30,和需求一致。

注意:不要在循环中反复调用np.append()拼接numpy数组,效率极低。

内容的提问来源于stack exchange,提问作者xxsou

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 19:36:44