2016-02-12 17 views
5

eines Histogramms Berechnung eines numpy Array betrachten, die Prozentsätze zurückgibt:Filtering Histogramms Kanten und Zählungen

# 500 random numbers between 0 and 10,000 
values = np.random.uniform(0,10000,500) 

# Histogram using e.g. 200 buckets 
perc, edges = np.histogram(values, bins=200, 
          weights=np.zeros_like(values) + 100/values.size) 

Die obigen kehrt zwei Arrays:

  • perc enthaltend die % (dh Prozentsätzen) von Werten innerhalb jedes Paar von aufeinander folgenden edges[ix] und edges[ix+1] von insgesamt.
  • edges der Länge len(hist)+1

Jetzt sagen, dass ich perc und edges so filtern mag, dass ich nur mit den Prozentangaben und Kanten für Werte in einen neuen Bereich [m, M] enthalten enden. "

Das heißt, möchte ich mit den Subanordnungen von perc und edges entsprechend dem Intervall von Werten innerhalb [m, M] arbeiten. Es ist unnötig zu erwähnen, dass sich die neue Anordnung von Prozentsätzen immer noch auf die Gesamtbruchzahl des Eingabearrays bezieht. Wir wollen nur perc und edges filtern, um mit den richtigen Sub-Arrays zu enden. Wie kann ich perc und edges nachbearbeiten, um dies zu tun?

Die Werte m und M können natürlich beliebig sein. In dem obigen Beispiel können wir z.B. m = 0 und M = 200.

Antwort

2
m = 0; M = 200 
mask = [(m < edges) & (edges < M)] 
>>> edges[mask] 
array([ 37.4789683 , 87.07491593, 136.67086357, 186.2668112 ]) 

Lassen Sie uns die Arbeit an einem kleineren Datenmenge, so dass es leichter zu verstehen:

np.random.seed(0) 
values = np.random.uniform(0, 100, 10) 
values.sort() 
>>> values 
array([ 38.34415188, 42.36547993, 43.75872113, 54.4883183 , 
     54.88135039, 60.27633761, 64.58941131, 71.51893664, 
     89.17730008, 96.36627605]) 

# Histogram using e.g. 10 buckets 
perc, edges = np.histogram(values, bins=10, 
          weights=np.zeros_like(values) + 100./values.size) 

>>> perc 
array([ 30., 0., 20., 10., 10., 10., 0., 0., 10., 10.]) 

>>> edges 
array([ 38.34415188, 44.1463643 , 49.94857672, 55.75078913, 
     61.55300155, 67.35521397, 73.15742638, 78.9596388 , 
     84.76185122, 90.56406363, 96.36627605]) 

m = 0; M = 50 
mask = (m <= edges) & (edges < M) 
>>> mask 
array([ True, True, True, False, False, False, False, False, False, 
     False, False], dtype=bool) 

>>> edges[mask] 
array([ 38.34415188, 44.1463643 , 49.94857672]) 

>>> perc[mask[:-1]][:-1] 
array([ 30., 0.]) 

m = 40; M = 60 
mask = (m < edges) & (edges < M) 
>>> edges[mask] 
array([ 44.1463643 , 49.94857672, 55.75078913]) 
>>> perc[mask[:-1]][:-1] 
array([ 0., 20.]) 
+0

Danke, aber wie verwenden wir jetzt 'mask' auch filtern' perc'? –

1

Nun einige Mathematik für diese benötigen. Die Behälter sind gleich beabstandet, so kann man bestimmen, welche Behälter ist die erste aufzunehmen und welche die letzte von der Breite jedes Bins verwendet:

bin_width = edges[1] - edges[0] 

nun die erste und letzte gültige bin berechnen:

first = math.floor((m - edges[0])/bin_width) + 1 # How many bins from the left 
last = math.floor((edges[-1] - M)/bin_width) + 1 # How many bins from the right 

(Ignorieren Sie die 1 für beide, wenn Sie den Behälter enthält m oder M enthalten sein sollen - aber dann vorsichtig sein, dass Sie nicht mit negativen Werten für das erste Ende und letzte)

Jetzt wissen Sie, wie viele Behälter enthalten:

valid_edges = edges[first:-last] 
valid_perc = perc[first:-last] 

die ersten first Punkte und die letzten last Punkte Mit diesem Ausschluß.

Könnte sein, dass ich nicht genug Aufmerksamkeit auf die Rundung aufgepasst habe und es ist ein "off by one" -Fehler enthalten, aber ich denke, die Idee ist gesund. :-)

Sie müssen wahrscheinlich spezielle Fälle wie M > edges[-1] fangen, aber aus Gründen der Lesbarkeit habe ich diese nicht aufgenommen.


Oder wenn die Behälter verwenden boolean Masken anstelle der Berechnung nicht mit gleichem Abstand zu:

first = edged[edges < m].size + 1 
last = edged[edges > M].size + 1