2016-12-03 72 views
0

下面的代碼可以讓我找到匹配的值:返回塔提供匹配值的平均值

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)) 

信息關於這個可以發現here

更好的解釋是從@Andras迪克

sum()中的生成器表達式循環遍歷每個列對,並構造相應的布爾向量。對每個列對求和,並將結果列附加到數據幀「。

實施例輸出脫粒= 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 

我怎樣才能返回另一個柱df['matches_mean']提供具有匹配的值的平均值?因此,對於上面示例中的第一行,將返回平均值0.146360 & -0.099707。我希望使用與原始代碼相同的itertools combinations邏輯,因爲這可以很好地適應我的真實數據。

+0

如果多於一對列的接近什麼?該專欄應包含哪些內容? –

+0

你好安德拉斯。我最終尋找大多數比賽以及這場比賽的平均數。所以如果3列匹配並且2匹配來自同一行,那麼3列的平均值將是理想的。謝謝你的幫助! – ade1e

+0

那麼沒有匹配的行呢? –

回答

1

暫時這裏是一個幾乎完美的解決方案。問題是,當你想計算多個匹配的平均值(比如說,一行中的所有三個數字都接近閾值)時,你需要在計算平均值時取適當數量的值。如果3列中只有1或3個匹配,這很容易。但是,當兩對數字「接近」但第三對不是時,下面的代碼將會出現錯誤。

這個想法是總結每行和每個組合的匹配值。例如,如果只有行'A''B'「接近」(在閾值內),我們得到df.A+df.B,其必須除以2以得到平均值。當所有三個「接近」時,我們得到2*df.A + 2*df.B + 2*df.C,其可以被6除以得到適當的平均值。但是,在第三種情況下,例如,我們得到df.A + 2*df.B + df.C(當A和B接近時,B和C接近,但A和C不接近)。在這種情況下,我們不能用任何東西來劃分,以獲得適當的意思。我們可能應該用4除以得到「大約一個」元素的錯誤含義。我的觀點是,如果我們要妥善處理這種情況,那麼代碼會複雜得多,根據您的需要,這可能不值得。目前還不清楚你要如何處理這個案件。當前版本除以4,相當於平均A與B,平均B與C,然後再次平均這些平均值。

所以這裏有雲:

import numpy as np 
import pandas as pd 
from itertools import combinations 

colnames = ['A', 'B', 'C'] 
df = pd.DataFrame(np.random.randn(12, 3), columns=colnames) 
thresh = .3 
df['matches'] = sum(abs(df[k1]-df[k2])<thresh 
        for k1,k2 in combinations(colnames,2)) 
# this is your starting point, we'll need df['matches'] too 

tmpsums = sum(np.where(abs(df[k1]-df[k2])<thresh,df[k1]+df[k2],0) 
       for k1,k2 in combinations(colnames,2)) 
# divide by 2/4/6: 
df['matches_mean'] = np.where(df['matches'],tmpsums/df['matches']/2,0) 

在發電機表達的出現總和達到口感好等限制,我承認。你可能想把它寫在適當的for循環中,但是你必須遞增地總結tmpsums中的值。我承認這可能更漂亮。

無論如何,這第二個生成器表達式的工作方式與第一個類似。該產生價值當然是不同的,它是

np.where(abs(df[k1]-df[k2])<thresh,df[k1]+df[k2],0) 

也就是說,它會給我們給定的列對,如果這些值比脫粒接近的元素的總和,否則我們得到0。對於所有3組合我們得到一個具有這樣的零或者兩個和的元素值的數組,並且我們再次總結它們。在有0個匹配的情況下,我們得到0.如果有1個匹配,我們總結兩個匹配元素。對於2場比賽,我們得到了前面提到的混合總和,並且在3場比賽中我們有兩次所有術語。

剩下的是將非零例除以匹配的數量,這只是一個分割,其中我們已經知道的匹配數量是兩倍(但我們必須注意零除)。

實施例輸出與thresh = 0.3

  A   B   C matches matches_mean 
0 0.716278 0.681279 0.861410  3  0.752989 
1 -0.109029 -0.646952 0.268038  0  0.000000 
2 -1.095221 -1.088397 1.100645  1  -1.091809 
3 -1.970372 -0.367096 -0.337098  1  -0.352097 
4 -1.030003 0.082001 -0.807431  1  -0.918717 
5 1.660611 -0.046429 0.557107  0  0.000000 
6 -0.508715 -0.588217 0.014917  1  -0.548466 
7 0.578028 -0.187097 -0.420243  1  -0.303670 
8 0.233687 1.311917 1.888947  0  0.000000 
9 0.478863 1.087957 -0.897025  0  0.000000 
10 -0.001462 0.866320 -1.198642  0  0.000000 
11 0.297946 0.564325 -1.098887  1  0.431135 
+0

謝謝@Andras迪克這是偉大的。我已標記爲完整,但會再提出一個問題。無論如何要添加顯示匹配模式的另一列,即如果所有匹配都在閾值內,則顯示「df.A/df.B/df.C」的字符串。或者對於更大的數據集,如果在同一行上的不同匹配顯示,即如果看到兩個單獨的匹配組,則顯示「df.A/df.B/df.C」 - 「df.D/df.L/df.Z」 。我不知道這是否可以做到誠實。 – ade1e

+0

@adele謝謝。這絕對是可行的,它只需要更多的工作:)如果你想構建這樣的字符串,我不認爲這將以矢量化的方式工作。這意味着你可能不得不循環你的行,這不能很好地擴展。所以,假設你的意思是如果它可以有效地做到這一點:我不這麼認爲:( –