2
votes

Faire la synthèse des données sur des plages (multiples) spécifiques

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.


0 commentaires

3 Réponses :


2
votes

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)


0 commentaires


2
votes

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]


0 commentaires