2017-01-27 38 views
2

我有四列值:'A','B','C'和'D',一列包含四個字母之一。使用numpy ufuncs修改熊貓數據幀的位置

  Letter A B C D   max 
12063289  D 5 9 0 39    0 
12063290  D 3 25 0 79    0 
12063291  B 0 232 0 0    0 
12063292  A 351 0 0 0    0 
12063293  D 0 0 0 394    0 

根據字母列的值,我想計算其他三列的最大值。

  Letter A B C D   max 
12063289  D 5 9 0 39    9 
12063290  D 3 25 0 79    25 
12063291  B 0 232 0 16    16 
12063292  A 351 0 200 0    200 
12063293  D 0 0 0 394    0 

說上面的數據被存儲在一個變量DF,我試圖做到以下幾點:

import numpy as np 
import pandas as pd 

columns = {'A':['B','C','D'], 
      'B':['A','C','D'], 
      'C':['A','B','D'], 
      'D':['A','B','C']} 
for letter in ['A', 'B', 'C', 'D']: 
    mask = df.loc[df['Letter']==letter] 
    np.max(df[mask][columns[letter]], out=df[mask]['max']) 

我基本上要max函數工作只在蒙面數據框的相關列和寫回完全正確的位置,但大熊貓的原始數據幀(DF)的「最大」列抱怨在最後一行:

ValueError: Must pass DataFrame with boolean values only 

的問題是如何定位準確茨艾倫這些行的e單元接收max()函數的輸出,以便不使用不必要的空間(我可以使用apply函數執行此操作,但它佔用了大量的空間,我沒有)。

+0

所以,'Letter'已經從每行最大的人的ID? – Divakar

+0

'Letter'具有與計算每個相應行中的最大值無關的列的ID。在第一行中,如果Letter是'D',那麼該列的最大值應該從列'A','B'和'C'計算。 – tobsecret

回答

1

apply

cols = list('ABCD') 
df.apply(lambda x: x.loc[cols].drop(x.Letter).max(), 1) 

12063289  9 
12063290  25 
12063291  16 
12063292 200 
12063293  0 
dtype: int64 

​​query + groupby

d1 = df.set_index(
    'Letter', append=True 
)[list('ABCD')].rename_axis('Col', 1).stack().to_frame('value') 
d1.query('Letter != Col').groupby(level=0).value.max() 

12063289  9 
12063290  25 
12063291  16 
12063292 200 
12063293  0 
dtype: int64 
+0

感謝您的回覆,與我的天真解決方案相比,df.apply解決方案將內存使用量減少了一半。但是,如果我使用您提供的兩種解決方案中的第一種,它仍然使用原始數據幀大小的8倍,是否有一種方法可以使用np.max的out =參數進行改進? – tobsecret