Je suis certain qu'il existe un bon moyen de le faire, mais je supprime les bons termes de recherche dans Google. Je vais donc demander ici à la place. Mon problème est le suivant:
J'ai 2 tableaux à 2 dimensions, tous deux avec les mêmes dimensions. Un tableau (tableau 1) est la précipitation accumulée aux points (x, y). L'autre (tableau 2) est la hauteur topographique de la même grille (x, y). Je veux résumer le tableau 1 entre les hauteurs spécifiques du tableau 2 et créer un graphique à barres avec des cases de hauteur topographique sur l'axe des x et les précipitations totales accumulées sur l'axe des y.
Je veux donc pouvoir déclarer une liste de hauteurs (disons [0, 100, 200, ..., 1000] ) et pour chaque bac, résumer toutes les précipitations qui se sont produites dans cette poubelle.
Je peux penser à quelques moyens compliqués de faire cela, mais je suppose qu'il y a probablement un moyen plus simple auquel je ne pense pas. Mon instinct est de parcourir ma liste de hauteurs, de masquer tout ce qui se trouve en dehors de cette plage, de résumer les valeurs restantes, de les ajouter à un nouveau tableau et de répéter.
Je me demande s'il existe une bibliothèque numpy intégrée ou similaire qui peut le faire plus efficacement.
3 Réponses :
Ce code montre ce que vous demandez, quelques explications dans les commentaires:
result = []
for lower, upper in bands:
include = vin_range(height, lower, upper)
values_to_include = rainfall[include]
sum_of_rainfall = sum(values_to_include)
result.append(([lower, upper], sum_of_rainfall))
L'avant-dernière ligne est l'endroit où la magie opère. vin_range (height, * band) utilise la fonction vectorisée pour créer un tableau numpy de valeurs booléennes, avec les mêmes dimensions que height , qui a True si une valeur de height est dans la plage donnée, ou False sinon.
En utilisant ce tableau pour indexer le tableau avec les valeurs cibles ( pluie code >), vous obtenez un tableau qui ne contient que les valeurs pour lesquelles la hauteur est dans la plage cible. Ensuite, il suffit de les additionner.
En plus d'étapes que result = [(band, sum (rain [vin_range (height, * band)])) pour la bande en bandes] code> (mais avec le même résultat):
import numpy as np
def in_range(x, lower_bound, upper_bound):
# returns wether x is between lower_bound (inclusive) and upper_bound (exclusive)
return x in range(lower_bound, upper_bound)
# vectorize allows you to easily 'map' the function to a numpy array
vin_range = np.vectorize(in_range)
# representing your rainfall
rainfall = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
# representing your height map
height = np.array([[1, 2, 1], [2, 4, 2], [3, 6, 3]])
# the bands of height you're looking to sum
bands = [[0, 2], [2, 4], [4, 6], [6, 8]]
# computing the actual results you'd want to chart
result = [(band, sum(rainfall[vin_range(height, *band)])) for band in bands]
print(result)
Un exemple utilisant le module numpy ma a> qui permet de faire des tableaux masqués. À partir de la documentation: Un tableau masqué est la combinaison d'un numpy.ndarray standard et d'un masque. Un masque est soit nomask, indiquant qu'aucune valeur du tableau associé n'est invalide, soit un tableau de booléens qui détermine pour chaque élément du tableau associé si la valeur est valide ou non. qui semble ce dont vous avez besoin dans ce cas. Le numpy.ma.masked_where renvoie un tableau masqué où la condition est
import numpy as np
pr = np.random.randint(0, 1000, size=(100, 100)) #precipitation map
he = np.random.randint(0, 1000, size=(100, 100)) #height map
bins = np.arange(0, 1001, 200)
values = []
for vmin, vmax in zip(bins[:-1], bins[1:]):
#creating the masked array, here minimum included inside bin, maximum excluded.
maskedpr = np.ma.masked_where((he < vmin) | (he >= vmax), pr)
values.append(maskedpr.sum())
values est la liste des valeurs pour chaque bac, que vous peut tracer. True . Vous devez donc définir la condition sur True en dehors des bacs.
La méthode sum () effectue la somme uniquement là où le tableau n'est pas masqué.
Vous pouvez utiliser np.bincount avec np.digitize . digitalize crée un tableau d'index de casier à partir du tableau de hauteur height et des limites de casier bins . bincount utilise ensuite les indices bin pour additionner les données du tableau rain.
# set up rain = np.random.randint(0,100,(5,5))/10 height = np.random.randint(0,10000,(5,5))/10 bins = [0,250,500,750,10000] # compute sums = np.bincount(np.digitize(height.ravel(),bins),rain.ravel(),len(bins)+1) # result sums # array([ 0. , 37. , 35.6, 14.6, 22.4, 0. ]) # check against direct method [rain[(height>=bins[i]) & (height<bins[i+1])].sum() for i in range(len(bins)-1)] # [37.0, 35.6, 14.600000000000001, 22.4]