2012-04-24 12 views
7

znasz szybkie/eleganckie rozwiązanie Python/Scipy/Numpy dla następującego problemu: Masz zestaw współrzędnych x, y z powiązanymi wartościami w (wszystkie tablice 1D). Teraz bin x i y na siatkę 2D (rozmiar BINSxBINS) i obliczyć kwantyle (takie jak mediana) wartości w dla każdego pojemnika, co powinno na końcu doprowadzić do tablicy 2D BINSxBINS z wymaganymi kwantylami.Binowanie kwantowe/mediany/2D w Pythonie

Jest to łatwe do zrobienia z niektórymi zagnieżdżonymi pętlami, ale jestem pewien, że istnieje bardziej eleganckie rozwiązanie.

Dzięki Mark

Odpowiedz

5

To co wymyśliłem, mam nadzieję, że jest to przydatne. To niekoniecznie jest czystsze lub lepsze niż użycie pętli, ale może uda Ci się zacząć coś lepszego.

import numpy as np 
bins_x, bins_y = 1., 1. 
x = np.array([1,1,2,2,3,3,3]) 
y = np.array([1,1,2,2,3,3,3]) 
w = np.array([1,2,3,4,5,6,7], 'float') 

# You can get a bin number for each point like this 
x = (x // bins_x).astype('int') 
y = (y // bins_y).astype('int') 
shape = [x.max()+1, y.max()+1] 
bin = np.ravel_multi_index([x, y], shape) 

# You could get the mean by doing something like: 
mean = np.bincount(bin, w)/np.bincount(bin) 

# Median is a bit harder 
order = bin.argsort() 
bin = bin[order] 
w = w[order] 
edges = (bin[1:] != bin[:-1]).nonzero()[0] + 1 
med_index = (np.r_[0, edges] + np.r_[edges, len(w)]) // 2 
median = w[med_index] 

# But that's not quite right, so maybe 
median2 = [np.median(i) for i in np.split(w, edges)] 

wziąć również spojrzeć na numpy.histogram2d

+0

dzięki, to wygląda już dobrze. ale wydaje się, że część mediana nie jest w pełni poprawna. na przykład kolejność jest określona w niewłaściwym wierszu. – Mark

+0

Tak, masz rację. –

+1

Używając 'np.histogram2d' można [bardzo łatwo] (https://stackoverflow.com/a/12588656/60982) robić binning, ale nie przez medianę. – letmaik

1

dziękuję za kodzie. Opierając się na nim znalazłem następujące rozwiązanie mojego problemu (jedynie nieznaczne modyfikacje kodu):

import numpy as np 
BINS=10 
boxsize=10.0 
bins_x, bins_y = boxsize/BINS, boxsize/BINS 
x = np.array([0,0,0,1,1,1,2,2,2,3,3,3]) 
y = np.array([0,0,0,1,1,1,2,2,2,3,3,3]) 
w = np.array([0,1,2,0,1,2,0,1,2,0,1,2], 'float') 

# You can get a bin number for each point like this 
x = (x // bins_x).astype('int') 
y = (y // bins_y).astype('int') 
shape = [BINS, BINS] 
bin = np.ravel_multi_index([x, y], shape) 


# Median 
order = bin.argsort() 
bin = bin[order] 
w = w[order] 
edges = (bin[1:] != bin[:-1]).nonzero()[0] + 1 
median = [np.median(i) for i in np.split(w, edges)] 

#construct BINSxBINS matrix with median values 
binvals=np.unique(bin) 
medvals=np.zeros([BINS*BINS]) 
medvals[binvals]=median 
medvals=medvals.reshape([BINS,BINS]) 

print medvals 
0

Z numpy/scipy to idzie tak:

import numpy as np 
    import scipy.stats as stats 

    x = np.random.uniform(0,200,100) 
    y = np.random.uniform(0,200,100) 
    w = np.random.uniform(1,10,100) 

    h = np.histogram2d(x,y,bins=[10,10], weights=w,range=[[0,200],[0,200]]) 
    hist, bins_x, bins_y = h 
    q = stats.mstats.mquantiles(hist,prob=[0.25, 0.5, 0.75]) 

    >>> q.round(2) 
    array([ 512.8 , 555.41, 592.73]) 

    q1 = np.where(hist<q[0],1,0) 
    q2 = np.where(np.logical_and(q[0]<=hist,hist<q[1]),2,0) 
    q3 = np.where(np.logical_and(q[1]<=hist,hist<=q[2]),3,0) 
    q4 = np.where(q[2]<hist,4,0) 

    >>>q1 + q2 + q3 + q4 
    array([[4, 3, 4, 3, 1, 1, 4, 3, 1, 2], 
    [1, 1, 4, 4, 2, 3, 1, 3, 3, 3], 
    [2, 3, 3, 2, 2, 2, 3, 2, 4, 2], 
    [2, 2, 3, 3, 3, 1, 2, 2, 1, 4], 
    [1, 3, 1, 4, 2, 1, 3, 1, 1, 3], 
    [4, 2, 2, 1, 2, 1, 3, 2, 1, 1], 
    [4, 1, 1, 3, 1, 3, 4, 3, 2, 1], 
    [4, 3, 1, 4, 4, 4, 1, 1, 2, 4], 
    [2, 4, 4, 4, 3, 4, 2, 2, 2, 4], 
    [2, 2, 4, 4, 3, 3, 1, 3, 4, 4]]) 

prob = [0,25, 0,5 , 0,75] jest domyślną wartością ustawień kwantyla, możesz ją zmienić lub ją opuścić.

+0

Niestety, to nie zadziała. 'mquantiles' działa tylko z danymi, które nie są binowane. – imsc

3

prostu próbuję to zrobić sam i brzmi to jak chcesz komendę „scipy.stats.binned_statistic_2d” z można znaleźć średnia, mediana, standardowy devation ani żadnej określonej funkcji dla trzeciego parametru danego pojemniki .

Zdaję sobie sprawę, że to pytanie zostało już odebrane, ale uważam, że jest to dobre rozwiązanie wbudowane.