J'ai 11 ans (2007 à 2017) des fichiers quotidiens de température. Il existe un total de 11 * 365 = 4015
fichiers NetCDF. Chaque fichier contient des dimensions de latitude (100,)
, de longitude (360,)
et une variable de température de celles-ci de taille (360, 100)
. Je veux trouver la moyenne (mobile) sur 15 jours à chaque point de la grille en ignorant les valeurs NaN
si présentes. Cela signifie que 15 fichiers doivent être utilisés pour trouver la moyenne. J'ai la fonction suivante pour lire tous les fichiers quotidiens à partir d'un dossier. par exemple. moyenne de files_list [0:15]
, files_list [1:16]
, files_list [2:17] ....
, files_list [4000:]
doivent être trouvés. Et chaque fichier doit être enregistré en tant que nouveau fichier NetCDF. J'ai une idée de créer un fichier NetCDF. Mais impossible de trouver la moyenne courante ou mobile.
Voici mon code:
def files_list (working_dir, extension): ''' input = working directory and extension of file(eg. *.nc) outout = returns the list of files in the folder ''' file_full_path = os.path.join(working_dir) os.chdir(working_dir) files = glob.glob(os.path.join(file_full_path,extension)) files = natsort.natsorted(files) files_list= [] #Empty lsit of files j = 0 for j in range(0,len(files)): files_list.append(os.path.basename(files[j])) #appending each files in a directory to file list return files_list
3 Réponses :
Quant à mon commentaire ci-dessus:
"Combien d'éléments avez-vous dans chaque fichier? ... Si chaque fichier contient des milliers de points de grille, je voudrais Commencez par trier les différents points de la grille pour séparer les fichiers. Chaque Le fichier contiendra le même point de grille pour toutes les dates, triées par date. Ce comment il serait simple de charger un fichier entier d'un seul point de grille et calculez une moyenne mobile dessus. "
Maintenant que vous avez un fichier pour un seul point de grille, je chargerais les données dans une liste et exécuterais ce simple calcul de moyenne courante. (Étant donné que vous avez accès à l'ensemble de données, vous pouvez utiliser ce code. Pour les cas où la moyenne est calculée à l'exécution et où il n'y a pas d'historique des résultats, vous pouvez utiliser les algorithmes spécifiés ici: Wikipedia - Moyenne mobile )
[1, 2, 3, 4, 5, 6, 7, 8, 9] 2.0 3.0 4.0 5.0 6.0 7.0 8.0
Le résultat est: p >
#Generate a list of 10 items my_gridpoints_data=[x for x in range(1, 11)] print(my_gridpoints_data) #The average calculation window is set to 3, so the average is for 3 items at a time avg_window_width: int = 3 avg: float = 0.0 sum: float = 0.0 # Calculate the average of the first 3 items (avg_window_width is 3) for pos in range(0, avg_window_width): sum = sum + my_gridpoints_data[pos] avg = sum / avg_window_width print(avg) # Then move the window of the average by subtracting the leftmost item # and adding a new item from the right # Do this until the calculation window reaches the list's last item for pos in range(avg_window_width, my_gridpoints_data.__len__()): sum = sum + my_gridpoints_data[pos] - my_gridpoints_data[pos - avg_window_width] avg = sum/avg_window_width print(avg)
pourquoi se séparer en points de grille? ce serait une approche extrêmement lente. Si vous effectuez la même opération partout, il n'y a aucune raison pour que vous puissiez opérer sur l'ensemble du domaine.
@AdrianTompkins, j'ai suggéré de séparer les points de la grille avant d'effectuer le calcul, car je n'ai aucune idée de la taille de l'ensemble de données. Nous savons qu'il se compose d'environ 4000 fichiers, mais peut-être que chaque fichier contient des données pour un million de points. L'organisation des données avant le calcul permet un algorithme plus simple pour le calcul de la moyenne.
Ce n'est pas une solution en python, mais si vos fichiers sont appelés file_20061105.nc etc etc, vous pouvez les fusionner avec cdo (opérateurs de données climatiques) à partir de la ligne de commande puis utiliser la fonction runmean
for year in {2007..2017} ; do cdo mergetime file_${year}????.nc merged_${year}.nc done cdo mergetime merged_????.nc merged_file.nc cdo runmean,15 merged_file.nc runmean.nc
Un peu tard pour répondre mais pour quelqu'un qui lira à l'avenir, xarray
fournit également une solution Pythonic simple très similaire à la réponse @Adrian Tomkins, où l'on peut d'abord fusionner les fichiers de chaque année, puis fusionner les ensemble dans un fichier en raison de la limite du nombre de fichiers qui peuvent être ouverts dans un système.
for yr in range(2011,2018): file_name = str(yr) + 'merge.nc' xr.open_mfdataset(str(yr)*, combine='nested', concat_dim='time').to_netcdf(file_name) xr.open_mfdataset(*merge.nc, combine='nested', concat_dim='time').to_netcdf(merge_all.nc) ds = xr.open_dataset(merge_all.nc, chunks={'lat'=10, 'lon'=10}) # option to chunk if file size is too large, can also be used earlier with open_mfdataset ds_rolling_mean = ds.rolling(time=15, center=True).mean()
Edit: Un gros avantage de xarray
par rapport aux autres classiques C'est que l'on peut facilement faire des calculs en dehors de la mémoire et mettre à l'échelle vos calculs sur plusieurs cœurs grâce à dask
. Par exemple, si vous devez effectuer un prétraitement de vos fichiers avant la fusion, alors xr.open_mfdataset
prend une fonction de prétraitement définie par l'utilisateur comme argument preprocess
et définissant 'parallel = True 'pré-traitera vos fichiers d'entrée en parallèle avant la fusion.
Combien d'éléments avez-vous dans chaque fichier? Veuillez partager un extrait d'un tel fichier. Si chaque fichier contient des milliers de points de grille, je commencerais par trier les différents points de grille pour séparer les fichiers. Chaque fichier contiendra le même point de grille pour toutes les dates, triées par date. De cette façon, il serait simple de charger un fichier entier d'un seul point de grille et de calculer une moyenne mobile dessus.
Copie possible de Moyenne mobile ou moyenne courante