'Creating a bunch of figures with a Xarray multiple file dataset

I have a bunch of .grib files that I would like to be able to read in and create figures for. I have the code to load one file and plot a figure, but I'd like to figure out the best way to loop it so I don't have to change the filename and other parameters for each file. So far, I've switched from using xr.open_dataset to xr.open_mfdataset. I've tried doing a For Loop using time, but I get an error at plot = ax.contourf saying, "TypeError: Input Z must be 2D, not 3D." The dataset involves latitude, longitude, t2m (2-m air temperature), and time. See below code and attached image.

ds=xr.open_mfdataset('./Data/ecmwf_dataset/t2m/*.grib', combine='nested', concat_dim='time',
                     engine='cfgrib',backend_kwargs={'indexpath': ''})

lons = ds['longitude'][:]
lats = ds['latitude'][:]
sfcT = ds['t2m']
time = ds['time'].dt.strftime('%m-%d-%Y')

for i in range(len(ds.time)):
    fig = plt.figure(figsize=(10, 10))
    ax = fig.add_subplot(111, projection=ccrs.NorthPolarStereo(central_longitude=-47))     

    ax.set_extent([-180, 180, 60, 90], crs=ccrs.PlateCarree())
    lon2d,lat2d = np.meshgrid(lons,lats)

    min_plot_value = -4
    max_plot_value = 4
    contour_interval = 1
    clevs = np.arange(min_plot_value,max_plot_value+1,contour_interval)

    plot = xr.plot.contourf(lon2d, lat2d, sfcT.isel(time=i), clevs, cmap=plt.cm.RdBu_r, 
                       extend='both', transform=ccrs.PlateCarree())

    resol = '50m'
    land = cartopy.feature.NaturalEarthFeature('physical', 'land', \
      scale=resol, edgecolor='k', facecolor=cfeature.COLORS['land'])

    plt.savefig('./Figures/ArcticT2mAnom_'+str(time.values)+'.png', facecolor='white', dpi=300)

enter image description here

ValueError                                Traceback (most recent call last)
Input In [131], in <cell line: 1>()
     11 contour_interval = 1
     12 clevs = np.arange(min_plot_value,max_plot_value+1,contour_interval)
---> 14 plot = xr.plot.contourf(lon2d, lat2d, sfcT.isel(time=i),
     15                         clevs, cmap=plt.cm.RdBu_r, extend='both', transform=ccrs.PlateCarree())
     17 resol = '50m'  # use data at this scale
     18 land = cartopy.feature.NaturalEarthFeature('physical', 'land', \
     19     scale=resol, edgecolor='k', facecolor=cfeature.COLORS['land'])

File ~/opt/anaconda3/lib/python3.8/site-packages/xarray/plot/plot.py:1132, in _plot2d.<locals>.newplotfunc(darray, x, y, figsize, size, aspect, ax, row, col, col_wrap, xincrease, yincrease, add_colorbar, add_labels, vmin, vmax, cmap, center, robust, extend, levels, infer_intervals, colors, subplot_kws, cbar_ax, cbar_kwargs, xscale, yscale, xticks, yticks, xlim, ylim, norm, **kwargs)
   1126 elif rgb is not None and not imshow_rgb:
   1127     raise ValueError(
   1128         'The "rgb" keyword is only valid for imshow()'
   1129         "with a three-dimensional array (per facet)"
   1130     )
-> 1132 xlab, ylab = _infer_xy_labels(
   1133     darray=darray, x=x, y=y, imshow=imshow_rgb, rgb=rgb
   1134 )
   1136 xval = darray[xlab]
   1137 yval = darray[ylab]

File ~/opt/anaconda3/lib/python3.8/site-packages/xarray/plot/utils.py:382, in _infer_xy_labels(darray, x, y, imshow, rgb)
    376 def _infer_xy_labels(darray, x, y, imshow=False, rgb=None):
    377     """
    378     Determine x and y labels. For use in _plot2d
    379 
    380     darray must be a 2 dimensional data array, or 3d for imshow only.
    381     """
--> 382     if (x is not None) and (x == y):
    383         raise ValueError("x and y cannot be equal.")
    385     if imshow and darray.ndim == 3:

File ~/opt/anaconda3/lib/python3.8/site-packages/xarray/core/common.py:136, in AbstractArray.__bool__(self)
    135 def __bool__(self: Any) -> bool:
--> 136     return bool(self.values)

ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()


Solution 1:[1]

My code works after making these changes: "for i in range(len(ds.time)):" and "sfcT.isel(time=i)"

ds=xr.open_mfdataset('./Data/ecmwf_dataset/t2m/*.grib', combine='nested', concat_dim='time',
                     engine='cfgrib',backend_kwargs={'indexpath': ''})

lons = ds['longitude'][:]
lats = ds['latitude'][:]
sfcT = ds['t2m']
time = ds['time'].dt.strftime('%m-%d-%Y')

for i in range(len(ds.time)):
    fig = plt.figure(figsize=(10,10))
    ax = fig.add_subplot(111, projection=ccrs.NorthPolarStereo(central_longitude=-47))
    ax.set_extent([-180, 180, 60, 90], crs=ccrs.PlateCarree())
    
    lon2d,lat2d = np.meshgrid(lons,lats)
 
    
    min_plot_value = -4
    max_plot_value = 4
    contour_interval = 1
    clevs = np.arange(min_plot_value,max_plot_value+1,contour_interval)

    plot = ax.contourf(lon2d, lat2d, sfcT.isel(time=i),
                            clevs, cmap=plt.cm.RdBu_r, extend='both', transform=ccrs.PlateCarree())

    resol = '50m'  # use data at this scale
    land = cartopy.feature.NaturalEarthFeature('physical', 'land', \
        scale=resol, edgecolor='k', facecolor=cfeature.COLORS['land'])

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Chris Turnbull