2017-01-27 40 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