2016-11-24 38 views
3

有人可以提出一種簡單的方法來實現下面的結果。將行和列總和應用於熊貓數據框中的單元格

數據:

data = np.array([ 
['','A','B'], 
['Yes',44,19], 
['No',116,128] 
]) 

df = pd.DataFrame(data=data[1:,1:],  
        index=data[1:,0],  
        columns=data[0,1:]) 

df: 
      A B 
    Yes 44 19 
    No 116 128 

對於每一個細胞,我想在列總數除以表總乘以行總計的總和(在這一點上,我不關心呼叫的值),因此細胞是\ A將是:

63 *三百零七分之一百六十零= 32.83

這些值來自:

63 = 44 + 19

160 = 44 + 116

307 = 44 + 19 + 116 + 128

任何簡單的方法來這樣做呢?

謝謝

編輯。 全部期望的結果(也,這個方法應該不管數據幀的行和列數...這可能是不同的工作)

32.83 30.17 
127.17 116.83 

回答

2

與上述方法相比,這種解決方案的優點在於它適合於一行,但恐怕可能是它結束的地方。

df.apply(lambda r: df.sum()[r.name]*df.sum(1)[r.index]/df.sum().sum()) 
+0

驚人...做得好 – Diego

+0

申請是有點慢,看到我的更新。 – jezrael

+0

是的,應用必然比矩陣乘法慢。 – IanS

3

您可以使用DataFrame.dotsumDataframes通過to_frameSeries創建和T

df = df.astype(int) 

print (df.sum(1).to_frame()) 
     0 
Yes 63 
No 244 

print (df.sum().to_frame()) 
    0 
A 160 
B 147 

print (df.sum(1).to_frame().dot(df.sum().to_frame().T).div(df.sum().sum())) 
       A   B 
Yes 32.833876 30.166124 
No 127.166124 116.833876 

時序

np.random.seed(1) 
df = pd.DataFrame(np.random.randint(10, size=(10,10))) 
df.columns = list('ABCDEFGHIJ') 
print (df) 

In [293]: %timeit (df.apply(lambda r: df.sum()[r.name]*df.sum(1)[r.index]/df.sum().sum())) 
100 loops, best of 3: 14.1 ms per loop 

In [294]: %timeit (df.sum(1).to_frame().dot(df.sum().to_frame().T).div(df.sum().sum())) 
1000 loops, best of 3: 1.19 ms per loop 
+0

你得到了邊緣....我想4個值,結果......一個爲每個小區。感謝 – Diego

+0

對於'A'和'B'是否一樣? – jezrael

+0

是的,這並不容易。請檢查答案。 – jezrael

2

首先,您需要將DataFrame中的值轉換爲整數(或浮點數):df=df.applymap(int)

然後你可以用.sum()函數得到每列和每一行的總和。 這裏你會失去DataFrame的形狀(你最終會得到兩個一維數組),所以需要重建。

然後你可以加上二者併除以總數。

所有這一切都在一起得出:

df= df.applymap(int) 

rowsums = pd.concat([df.sum(axis=1)] * 2, ignore_index=True, axis=1) 
colsums = pd.concat([df.sum(axis=0)] * 2, ignore_index=True, axis=1).transpose() 

colsums.index = rowsums.index 
rowsums.columns = colsums.columns 

newdata = colsums * rowsums 
newdata = newdata.divide(df.sum().sum()) 

這導致:

newdata: 
       A   B 
Yes 32.833876 30.166124 
No 127.166124 116.833876 
1

真正棘手:

我(可能是次優解):

import numpy as np 
import pandas as pd 
data = np.array([ 
    ['','A','B'], 
    ['Yes',44,19], 
    ['No',116,128] 
]) 

df = pd.DataFrame(data=data[1:,1:], 
        index=data[1:,0], 
        columns=data[0,1:]).apply(pd.to_numeric,axis=0) 
orig = df.copy() 
df['rowsum']=df.sum(axis=1) 
df.loc['colsum',:]=df.sum(axis=0) 
rowsums = df.copy() 
rowsums['A'] = rowsums['rowsum'] 
rowsums['B'] = rowsums['rowsum'] 
colsums = df.copy() 
colsums.loc['Yes',:] = colsums.loc['colsum',:] 
colsums.loc['No',:] = colsums.loc['colsum',:] 
print(rowsums.multiply(colsums).div(orig.sum().sum())) 

結果:

    A   B rowsum 
Yes  32.833876 30.166124 63.0 
No  127.166124 116.833876 244.0 
colsum 160.000000 147.000000 307.0 
相關問題