Python Pandas组基于列并获取最大值,但基于另一列排除

时间:2017-05-28 00:08:49

标签: python pandas

我正在处理一些数据,并希望拉出某个列的最大值,按不同的列分组。但是,我想根据另一列从最大计算中排除某些行。

示例:

df = pd.DataFrame({'Col1':['A','A','A','B','B','B','B'],
                   'Col2':['Build','Plan','Other','Test','Build','Other','Buy'],
                   'Col3':[2,5,17,5,13,12,12]})

我希望获得Col3的最大值,按Col1分组,同时排除Col2中包含“其他”的任何行。因此,'A'的Col3的最大值应为5,而不是17。

我能够使用以下代码获得Col3的最大Col3分组:df['new'] = df.groupby(['Col1'])['Col3'].transform(max)但是,对于A,这将给我一个17的值。

从其他线程中查看,我尝试使用:

x = df1.groupby(['Col1'])
x2 = x.apply(lambda g: g[g['Col2'] != 'Other'])

这似乎让我接近(它有按Col1分组的数据,并根据Col2删除了行)。但是,我似乎无法找到基于Col1获得Col3最大值的方法。

在Col2中使用“其他”删除所有行后,我最多可以使用x2['Col3'].max()来获取Col3的最大值。但是,我无法将Col3的最大值归为Col1。

我想知道是否有办法使用内置的Pandas功能来相对简单地完成这项工作,而不是创建一个全新的定制功能?

3 个答案:

答案 0 :(得分:3)

你可以尝试

df[df.Col2 != 'Other'].groupby('Col1').Col3.max()

Col1
A     5
B    13

要创建新列:

df['new']=df[df.Col2 != 'Other'].groupby('Col1').Col3.transform('max')
df['new'] = df.new.ffill()

    Col1    Col2    Col3    new
0   A       Build   2       5.0
1   A       Plan    5       5.0
2   A       Other   17      5.0
3   B       Test    5       13.0
4   B       Build   13      13.0
5   B       Other   12      13.0
6   B       Buy     12      13.0

说明:仅选择其中Col2值不等于'Other'的df行,groupby Col1,找到Col3的max。

Here是转换的文档: 它返回一个带有转换值的索引df,而不是聚合。

答案 1 :(得分:1)

使用groupby

混合它的另一种方法
df.groupby([df.Col2.ne('Other'), 'Col1']).Col3.max()[True]

Col1
A     5
B    13
Name: Col3, dtype: int64

答案 2 :(得分:0)

@Vaishali的答案是一个好的开始,但我认为特别是在应用ffill摆脱na时可能会有一些问题。 为了使这种方法起作用,您需要以特定方式对数据框进行排序。 说服,试试这个:

df = pd.DataFrame({'Col1':['A','A','A','B','B','B','B',"C", "C"],
               'Col2':['Build','Plan','Other','Test','Build','Other','Buy', "Buy","Other"],
               'Col3':[2,5,17,5,13,12,12,14,5]})
df = df.sample(frac=1) #shuffle rows

df['new']=df[df.Col2 != 'Other'].groupby('Col1')["Col3"].transform('max')
df['new'] = df.new.ffill()

您会得到不好的结果。

Col1    Col2    Col3    new
3   B   Test    5   13.0
7   C   Buy     14  14.0
6   B   Buy     12  13.0
1   A   Plan    5   5.0
0   A   Build   2   5.0
5   B   Other   12  5.0
8   C   Other   5   5.0
4   B   Build   13  13.0
2   A   Other   17  13.0

更好的解决方案: 首先定义此功能。

def new_transform(df, exclude_cond,gbycol,target, agg_fun, ignore_value=None):
    df['target_temp'] = df[target] 
    df.loc[eval(exclude_cond), 'target_temp'] = ignore_value
    tmp=df.groupby(gbycol)['target_temp'].transform(agg_fun)
    df.drop('target_temp', axis=1, inplace=True)
    return tmp

它将使用您的数据帧,exculde_cond作为字符串,groupby作为字符串或字符串列表,目标:我们将在其上进行计算的列名,聚合函数和被聚合函数忽略的值(无用)主要的agg函数)。

示例:

df = pd.DataFrame({'Col1':['A','A','A','B','B','B','B',"C", "C"],
                   'Col2':['Build','Plan','Other','Test','Build','Other','Buy', "Buy","Other"],
                   'Col3':[2,5,17,5,13,12,12,14,5]})
df = df.sample(frac=1)
df['new']=new_transform(df, "df['Col2']=='Build'", ['Col1'],'Col3', 'sum', np.nan)

我们得到正确的计算:

  Col1  Col2    Col3    new
3   B   Test    5     29.0
2   A   Other   17    22.0
4   B   Build   13    29.0
6   B   Buy     12    29.0
7   C   Buy     14    19.0
1   A   Plan    5     22.0
5   B   Other   12    29.0
0   A   Build   2     22.0
8   C   Other   5     19.0