Consiglio vivamente di dare un'occhiata ai progetti xarray
e dask
. L'utilizzo di questi potenti strumenti ti consentirà di suddividere facilmente il calcolo in blocchi. Questo porta due vantaggi: puoi calcolare dati che non si adattano alla memoria e puoi utilizzare tutti i core della tua macchina per prestazioni migliori. È possibile ottimizzare le prestazioni scegliendo opportunamente la dimensione del blocco (vedere documentation).
È possibile caricare i vostri dati da netCDF facendo qualcosa di semplice come
import xarray as xr
ds = xr.open_dataset(path_file)
Se si desidera pezzo i dati in anni lungo la dimensione tempo, poi si specifica il parametro chunks
(supponendo che coordinano l'anno è chiamato 'l'anno'):
ds = xr.open_dataset(path_file, chunks={'year': 10})
Dal momento che le altre coordinate non appaiono nel chunks
dict, quindi un unico pezzo verrà utilizzato per loro. (Vedi maggiori dettagli nella documentazione here.). Questo sarà utile per il tuo primo requisito, in cui desideri moltiplicare ogni anno con un array 2D. Si potrebbe fare semplicemente:
ds['new_var'] = ds['var_name'] * arr_2d
Ora, xarray
e dask
sono il risultato di calcolo pigramente. Al fine di attivare il calcolo effettivo, si può semplicemente chiedere xarray
per salvare il risultato al netCDF:
ds.to_netcdf(new_file)
Il calcolo viene attivato attraverso dask
, che si prende cura di dividere la trasformazione in pezzi e, quindi, consente di lavorare con dati che non si adattano alla memoria. Inoltre, dask
si occuperà di utilizzare tutti i core del processore per i pezzi di calcolo.
I progetti xarray
e dask
non gestiscono ancora bene le situazioni in cui i blocchi non "si allineano" bene per il calcolo parallelo. Dato che in questo caso ci siamo suddivisi solo nella dimensione "anno", non ci aspettiamo problemi.
Se si desidera aggiungere file insieme due diverse netCDF, è semplice come:
ds1 = xr.open_dataset(path_file1, chunks={'year': 10})
ds2 = xr.open_dataset(path_file2, chunks={'year': 10})
(ds1 + ds2).to_netcdf(new_file)
Ho fornito un esempio completamente funzionante utilizzando a dataset available online.
In [1]:
import xarray as xr
import numpy as np
# Load sample data and strip out most of it:
ds = xr.open_dataset('ECMWF_ERA-40_subset.nc', chunks = {'time': 4})
ds.attrs = {}
ds = ds[['latitude', 'longitude', 'time', 'tcw']]
ds
Out[1]:
<xarray.Dataset>
Dimensions: (latitude: 73, longitude: 144, time: 62)
Coordinates:
* latitude (latitude) float32 90.0 87.5 85.0 82.5 80.0 77.5 75.0 72.5 ...
* longitude (longitude) float32 0.0 2.5 5.0 7.5 10.0 12.5 15.0 17.5 20.0 ...
* time (time) datetime64[ns] 2002-07-01T12:00:00 2002-07-01T18:00:00 ...
Data variables:
tcw (time, latitude, longitude) float64 10.15 10.15 10.15 10.15 ...
In [2]:
arr2d = np.ones((73, 144)) * 3.
arr2d.shape
Out[2]:
(73, 144)
In [3]:
myds = ds
myds['new_var'] = ds['tcw'] * arr2d
In [4]:
myds
Out[4]:
<xarray.Dataset>
Dimensions: (latitude: 73, longitude: 144, time: 62)
Coordinates:
* latitude (latitude) float32 90.0 87.5 85.0 82.5 80.0 77.5 75.0 72.5 ...
* longitude (longitude) float32 0.0 2.5 5.0 7.5 10.0 12.5 15.0 17.5 20.0 ...
* time (time) datetime64[ns] 2002-07-01T12:00:00 2002-07-01T18:00:00 ...
Data variables:
tcw (time, latitude, longitude) float64 10.15 10.15 10.15 10.15 ...
new_var (time, latitude, longitude) float64 30.46 30.46 30.46 30.46 ...
In [5]:
myds.to_netcdf('myds.nc')
xr.open_dataset('myds.nc')
Out[5]:
<xarray.Dataset>
Dimensions: (latitude: 73, longitude: 144, time: 62)
Coordinates:
* latitude (latitude) float32 90.0 87.5 85.0 82.5 80.0 77.5 75.0 72.5 ...
* longitude (longitude) float32 0.0 2.5 5.0 7.5 10.0 12.5 15.0 17.5 20.0 ...
* time (time) datetime64[ns] 2002-07-01T12:00:00 2002-07-01T18:00:00 ...
Data variables:
tcw (time, latitude, longitude) float64 10.15 10.15 10.15 10.15 ...
new_var (time, latitude, longitude) float64 30.46 30.46 30.46 30.46 ...
In [6]:
(myds + myds).to_netcdf('myds2.nc')
xr.open_dataset('myds2.nc')
Out[6]:
<xarray.Dataset>
Dimensions: (latitude: 73, longitude: 144, time: 62)
Coordinates:
* time (time) datetime64[ns] 2002-07-01T12:00:00 2002-07-01T18:00:00 ...
* latitude (latitude) float32 90.0 87.5 85.0 82.5 80.0 77.5 75.0 72.5 ...
* longitude (longitude) float32 0.0 2.5 5.0 7.5 10.0 12.5 15.0 17.5 20.0 ...
Data variables:
tcw (time, latitude, longitude) float64 20.31 20.31 20.31 20.31 ...
new_var (time, latitude, longitude) float64 60.92 60.92 60.92 60.92 ...
Sei sicuro che la lettura di qualsiasi altra questione (ad esempio l'intero file in una sola volta) sarebbe più veloce? Puoi provare con un file ritagliato? –
Qualsiasi [profilazione essenziale] (http://stackoverflow.com/questions/582336/how-can-you-profile-a-python-script) è stata completata? –
Stai facendo qualcosa con i dati dell'anno una volta che l'hai letto? Puoi leggere un intervallo di anni, ad es. '[1997: 2007,:,:]'? – hpaulj