Tengo una cantidad de coordenadas (aproximadamente 20000) para las que necesito extraer datos de una cantidad de archivos NetCDF, cada uno viene con aproximadamente 30000 pasos de tiempo (escenarios climáticos futuros). Usar la solución aquí no es eficiente y la razón es el tiempo empleado en cada i, j para convertir "dsloc" en "dataframe" (mire el código a continuación). ** se puede descargar un archivo NetCDF de ejemplo desde aquí **
import pandas as pd import xarray as xr import time #Generate some coordinates coords_data = [{'lat': 68.04, 'lon': 15.20, 'stid':1}, {'lat':67.96, 'lon': 14.95, 'stid': 2}] crd= pd.DataFrame(coords_data) lat = crd["lat"] lon = crd["lon"] stid=crd["stid"] NC = xr.open_dataset(nc_file) point_list = zip(lat,lon,stid) start_time = time.time() for i,j,id in point_list: print(i,j) dsloc = NC.sel(lat=i,lon=j,method='nearest') print("--- %s seconds ---" % (time.time() - start_time)) DT=dsloc.to_dataframe() DT.insert(loc=0,column="station",value=id) DT.reset_index(inplace=True) temp=temp.append(DT,sort=True) print("--- %s seconds ---" % (time.time() - start_time))cuyo resultado es:
68.04 15.2 --- 0.005853414535522461 seconds --- --- 9.02660846710205 seconds --- 67.96 14.95 --- 9.028568267822266 seconds --- --- 16.429600715637207 seconds ---lo que significa que cada i, j tarda alrededor de 9 segundos en procesarse. Dadas muchas coordenadas y archivos netcdf con grandes intervalos de tiempo, me pregunto si existe una forma pitónica de optimizar el código. También podría usar operadores CDO y NCO, pero también encontré un problema similar al usarlos.
Tengo una solución potencial. La idea es convertir primero la matriz de datos de xarray en pandas, luego obtener un subconjunto del marco de datos de pandas en función de las condiciones de latitud/longitud.
# convert xarray data to a pandas dataframe def xr_to_df(data): data = data.to_dataframe() data.reset_index(inplace=True) return data # convert your xarray data to a pandas dataframe full_df = xr_to_df(full_xarray) # create a 2 columns pandas dataframe containing your target coordinates points = pd.DataFrame({'lat':target_lat, 'lon':target_lon}) # get the values at your target points only via merging on the left subset = pd.merge(points,full_df)No estoy seguro de su tamaño de datos, qué tan rápido será esto. Pero al menos, esto evita bucles. Supongo que debería ser más rápido?
Noté que tus puntos están distribuidos aleatoriamente (no en los centros de la cuadrícula). Para abordar esto, primero puede escribir sus propios códigos para volver a cuadricularlos en la resolución netcdf, use cosas como np.argmin(abs(lat - lat_netcdf)) para encontrar el lat y lon más cercano.
Este es un caso de uso perfecto para la indexación avanzada de xarray usando un índice DataArray.
# Make the index on your coordinates DataFrame the station ID, # then convert to a dataset. # This results in a Dataset with two DataArrays, lat and lon, each # of which are indexed by a single dimension, stid crd_ix = crd.set_index('stid').to_xarray() # now, select using the arrays, and the data will be re-oriented to have # the data only for the desired pixels, indexed by 'stid'. The # non-indexing coordinates lat and lon will be indexed by (stid) as well. NC.sel(lon=crd_ix.lon, lat=crd_ix.lat, method='nearest') Se ignorarán otras dimensiones en los datos, por lo que si sus datos originales tienen dimensiones (lat, lon, z, time) sus nuevos datos tendrán dimensiones (stid, z, time) .