2014-01-20 17 views
1

我有問題排序列表項目到垃圾箱。我有兩個列表,X和Y,帶有相應的X和Y值(顯然也可以是一個元組列表)。接下來,我需要將X範圍分成10個相等的分箱,並將X值和相應的Y值分類到這些分箱,以便我知道Y值屬於哪個X bin(即,哪個分箱落入每個Y的X值值),然後取每個箱中所有Y值的中位數。這給了我十個bin-median對。原則上使用下面的代碼我也可以計算每個垃圾箱的X中心。Binning python元組。由於空箱子錯誤

bins = np.linspace(max(X), min(X), 10) 
    digitized = np.digitize(X, bins) 
    bin_centers = [] 
    for j in range(len(bins) - 1): 
     bin_centers.append((bins[j] + bins[j + 1])/2.) 
    bin_means = [np.median(np.asarray(Y)[digitized == j]) 
       for j in range(1, len(bins))] 

現在的問題是,有時一個bin是空的,因爲在這個bin中沒有X值。在這種情況下,行

bin_means = [np.median(np.asarray(Y)[digitized == j]) 
       for j in range(1, len(bins))] 

提高,因爲空箱的錯誤

/usr/lib64/python2.6/site-packages/numpy/core/_methods.py:55: RuntimeWarning: Mean of empty slice. 
FloatingPointError: invalid value encountered in double_scalars 

。我該如何解決這個問題?我也嘗試right=True/False​​沒有運氣。我認爲最好先刪除列表bin_centersdigitizedbins中的條目,然後再執行計算中值的列表理解。但我不知道如何做到這一點,如何找出哪些垃圾箱是空的,然後從這些列表中刪除什麼以及如何刪除。 任何想法?謝謝!

+0

這到底是怎麼回事?什麼是「X」和「Y」? 「X」中的值與「Y」中的值相對應? –

+0

它們包含的數字基本上是任意的,只要每個數字x屬於一個數值y,所以有成對(x1,y1),(x2,y2)等等。在我的情況下,X包含大小,Y包含每個x值的大小偏差。繪製出一個X/Y散點圖。 – frixhax

回答

1

如果你有SciPy的,你可以調用scipy.stats.binned_statistic

import scipy.stats as stats 
statistic, bin_edges, binnumber = stats.binned_statistic(
    x=X, values=Y, statistic='median', bins=bins) 
statistic = statistic[np.isfinite(statistic)] 
print(statistic) 

產生

[ 15. 90. 50. 55. 40. 60.] 

沒有SciPy的,我想你會需要一個列表理解。 正如您所建議的那樣,您可以通過過濾掉那些空的垃圾箱來避免RuntimeWarning。你可以做到這一點與在列表解析裏的if-condition

masks = [(digitized == j) for j in range(1, len(bins))] 
bin_medians = [np.median(Y[mask]) for mask in masks if mask.any()] 

另外請注意,您所看到的錯誤消息是警告,也不例外。你可以(或者)取消錯誤消息

import warnings 
warnings.filterwarnings("ignore", 'Mean of empty slice.') 
warnings.filterwarnings("ignore", 'invalid value encountered in double_scalar') 

有一種方法可以更快地計算bin_centers:

bin_centers = [] 
for j in range(len(bins) - 1): 
    bin_centers.append((bins[j] + bins[j + 1])/2.) 

可以簡化爲

bin_centers = bins[:-1] + (bins[1]-bins[0])/2 

因此,例如,

import numpy as np 
import matplotlib.pyplot as plt 
import warnings 
warnings.filterwarnings("ignore", 'Mean of empty slice.') 
warnings.filterwarnings("ignore", 'invalid value encountered in double_scalar') 

np.random.seed(123) 

X = np.random.random(10) 
bins = np.linspace(min(X), max(X), 10) 
digitized = np.digitize(X, bins)-1 
bin_centers = bins + (bins[1]-bins[0])/2 

Y = range(0, 100, 10) 
Y = np.asarray(Y, dtype='float') 
bin_medians = [np.median(Y[digitized == j]) for j in range(len(bins))] 
print(bin_medians) 

plt.scatter(bin_centers, bin_medians) 
plt.show() 

產生

[15.0, 90.0, 50.0, 55.0, nan, 40.0, nan, nan, nan, 60.0] 

enter image description here

如果你的目的只是讓散點圖,那麼就沒有必要刪除的NaN,因爲matplotlib反正會忽略它們。

如果你真的要刪除的NaN,那麼你可以使用

no_nans = np.isfinite(bin_medians) 
bin_medians = bin_medians[no_nans] 
bin_centers = bin_centers[no_nans] 

在上面,我選擇了使用warnings.filterwarnings只是抑制警告。如果你不希望禁止警告,寧可從bin_medians過濾NaN,並且從相應的位置從bin_centers,則:

bin_centers = bins + (bins[1]-bins[0])/2 
masks = [(digitized == j) for j in range(len(bins))] 
bin_centers, bin_medians = zip(*[(center, np.median(Y[mask])) 
           for center, mask in zip(bin_centers, masks) 
           if mask.any()]) 
+0

謝謝,這可能是我正在尋找的!有兩個問題:我還需要擺脫對應於空箱的bin_center條目,因爲我需要繪製散點圖(bin_centers,bin_medians)。有沒有更好的方法來將它們踢出去比在for循環中爲'mask.any()'爲'False'的指數('for in in range(len(masks)):if not mask.any ):del_index.append(i)'然後'bin_centers = [m爲n,m爲枚舉(bin_centers)如果n不在del_index中]'?還有,爲什麼列表中有六個元素與scipy一起且只有五個與 – frixhax

+0

我知道它必須是'如果不是掩飾[i] .any()',對不起;) – frixhax

+0

或者更確切地說任何(掩碼[i]),因爲它不是一個numpy數組 – frixhax

0

我不太明白的問題,但這裏的東西,也許你開始:

In [3]: X = [1,2,3,4,5,6,7,8,9,10] 

In [4]: Y = [chr(96+x) for x in X] 

In [8]: Z = zip(X, Y) # Create a pairing - this can be done after a sort if they're not in whatever 'order' you want for your correspondence 

In [9]: Z 
Out[9]: 
[(1, 'a'), 
(2, 'b'), 
(3, 'c'), 
(4, 'd'), 
(5, 'e'), 
(6, 'f'), 
(7, 'g'), 
(8, 'h'), 
(9, 'i'), 
(10, 'j')] 

在這一點上,你可以這樣做sorted(Z, key=lambda el: -ord(el[1]))或任何排序根據您的標準。顯然它比例子更有意義。

最後,要分成等長的部分,我想你可能也想看看wide variety of possibilities given as answers here

如果這不是你要找的,道歉。