2016-12-02 123 views
2

使用以下試驗數據:函數在多個列匹配值

df2 = pd.DataFrame(np.random.randn(12, 3), columns=['A', 'B', 'C']) 
thresh = .3 
df2['matches'] = np.where(df2.A - df2.B < thresh,1,0) 

我創建的df2['matches']柱表示1df2.A - df2.B < thresh的值。

 A   B   C  matches 
0 0.501554 -0.589855 -0.751568 0 
1 -0.295198 0.512442 0.466915 1 
2 0.074863 0.343388 -1.700998 1 
3 0.115432 -0.507847 -0.825545 0 
4 1.013837 -0.007333 -0.292192 0 
5 -0.930738 1.235501 -0.652071 1 
6 -1.026615 1.389294 0.035041 1 
7 0.969147 -0.397276 1.272235 0 
8 0.120461 -0.634686 -1.123046 0 
9 0.956896 -0.345948 -0.620748 0 
10 -0.552476 1.376459 0.447807 1 
11 0.882275 0.490049 0.713033 0 

不過,我其實想比較這三個列,如果值是內thresh它將返回匹配的df2['matches]量相應的數字。因此,例如,如果Col A = 1,B = 2和C = 1.5且thresh爲.5,則函數將在['matches']列中返回3。

有沒有一個功能已經做了類似的事情或任何人都可以幫助嗎?

回答

2

您可以使用每對列的閾值,然後總結得到的布爾列以獲得您需要的數字。但請注意,該數字取決於您比較列的順序。如果你使用了abs(df['A']-df['B'])等,這種含糊不清的情況將會消失,這可能是你的意圖。下面我會假設這是你需要的。在每列對

from itertools import combinations 
df = pd.DataFrame(np.random.randn(12, 3), columns=['A', 'B', 'C']) 
thresh = .3 
df['matches'] = sum(abs(df[k1]-df[k2])<thresh for k1,k2 in combinations(df.keys(),2)) 

發電機表達在sum()迴路,並構造相應的布爾矢量:

一般來說,可以使用itertools.combinations以產生每對列一次。對每個列對彙總這些值,並將結果列附加到數據幀。

例輸出thresh = 0.3

  A   B   C matches 
0 0.146360 -0.099707 0.633632  1 
1 1.462810 -0.186317 -1.411988  0 
2 0.358827 -0.758619 0.038329  0 
3 0.077122 -0.213856 -0.619768  1 
4 0.215555 1.930888 -0.488517  0 
5 -0.946557 -0.904743 -0.004738  1 
6 -0.080209 -0.850830 -0.866865  1 
7 -0.997710 -0.580679 -2.231168  0 
8 1.762313 -0.356464 -1.813028  0 
9 1.151338 0.347636 -1.323791  0 
10 0.248432 1.265484 0.048484  1 
11 0.559934 -0.401059 0.863616  0 

使用itertools.combinations,列相比

>>> [k for k in itertools.combinations(df.keys(),2)] 
('A', 'B'), ('A', 'C'), ('B', 'C')] 

但如果您使用的絕對值(從那以後,真的沒關係差異相對於列是對稱的)。

+0

謝謝@Andras迪克。也許我的問題有問題,但第10行顯示了3個匹配,而1.260968和0.690971之間的差異> thresh。當數字之間的差值 ade1e

+0

@adele查看我的最後一個代碼塊:我們的順序是'('B','C')',所以我們計算'B'列減去'C'列,這對這種情況是負的。你可能希望它一路走去,通過交換在列表理解'k1'和'k2'(編輯;現在發電機的表情,裏面'總和()');但最可能的情況是你需要差異的絕對值,而不是差異本身。你明白我的意思嗎? –

+0

你能告訴我如何得到差異的絕對值,我會看看如果這給出了我期待的結果,謝謝 – ade1e

1

試試這個傢伙:

df2['matches'] = df2.apply(lambda x: sum([x[i] - x[j] <= thresh for i, j in [(0, 1), (0, 2), (1, 2)]]), axis=1) 

它必要時可推廣到任意數量的列。

-2

這裏有一個辦法做到這一點:

df2 = pd.DataFrame(np.random.randn(12, 3), columns=['A', 'B', 'C']) 
thresh = 0.3 

newcol = [] 
for row in df2.iterrows(): 
    newcol.append(sum([v > thresh for v in list(row[1])])) 
df2['matches'] = newcol 
+0

「有多少列>門檻」可以用更少的工作負責;這不是問題。 –