Pandas:将groupby的结果分配给dataframe到新列

时间:2016-03-03 19:19:05

标签: python pandas group-by dataframe

我有以下玩具数据框(真正的玩具数据框有500k行):

df = pd.DataFrame({'size': list('SSMMMLS'),
                   'weight': [8, 10, 11, 1, 20, 14, 12],
                   'adult' : [False] * 5 + [True] * 2})

   adult size  weight
0  False    S       8
1  False    S      10
2  False    M      11
3  False    M       1
4  False    M      20
5   True    L      14
6   True    S      12

并希望通过adult分组,选择weight最大的行,并在新列中size2分配size列值:

   adult size size2  weight
0  False    S     S       8
1  False    S     S      10
2  False    M     S      11
3  False    M     S       1
4  False    M     S      20
5   True    L     L      14
6   True    S     L      12

我找到了this,但它对我不起作用

到目前为止,我有:

df.loc[:, 'size2'] = df.groupby('adult',as_index=True)['weight','size']
                       .transform(lambda x: x.ix[x['weight'].idxmax()]['size'])

3 个答案:

答案 0 :(得分:3)

IIUC你可以使用merge。我认为size2中的第一个值是M,因为最大weight20

df = pd.DataFrame({'size': list('SSMMMLS'),
                   'weight': [8, 10, 11, 1, 20, 14, 12],
                   'adult' : [False] * 5 + [True] * 2})

print df
   adult size  weight
0  False    S       8
1  False    S      10
2  False    M      11
3  False    M       1
4  False    M      20
5   True    L      14
6   True    S      12

print df.groupby('adult').apply(lambda subf: subf['size'][subf['weight'].idxmax()]).reset_index(name='size2')                
   adult size2
0  False     M
1   True     L

print pd.merge(df, df.groupby('adult').apply(lambda subf: subf['size'][subf['weight'].idxmax()]).reset_index(name='size2'), on=['adult'])            
   adult size  weight size2
0  False    S       8     M
1  False    S      10     M
2  False    M      11     M
3  False    M       1     M
4  False    M      20     M
5   True    L      14     L
6   True    S      12     L

答案 1 :(得分:2)

使用您的数据框,更详细地了解@jazrael的答案:

df = pd.DataFrame({'size': list('SSMMMLS'),
                   'weight': [8, 10, 11, 1, 20, 14, 12],
                   'adult' : [False] * 5 + [True] * 2})
#    adult size  weight
# 0  False    S       8
# 1  False    S      10
# 2  False    M      11
# 3  False    M       1
# 4  False    M      20
# 5   True    L      14
# 6   True    S      12

获取最大重量线的大小值:

def size4max_weight(subf):
    """ Return size value for the max weight line """
    return subf['size'][subf['weight'].idxmax()]

成人'成群结队将生成一个False的Serie,True作为索引值::

>>> size2_col = df.groupby('adult').apply(size4max_weight)
>>> type(size2_col), size2_col.index
(pandas.core.series.Series, Index([False, True], dtype='object', name=u'adult'))

使用reset_index我们转换DataFrame ::

中的系列
>>> size2_col = df.groupby('adult').apply(size4max_weight).reset_index(name='size2')
>>> size2_col
   adult size2
0  False     M
1   True     L
>>>
成人'

pd.merge做到:

>>> pd.merge(df, size2_col, on=['adult'])
   adult size  weight size2
0  False    S       8     M
1  False    S      10     M
2  False    M      11     M
3  False    M       1     M
4  False    M      20     M
5   True    L      14     L
6   True    S      12     L

答案 2 :(得分:1)

您可以将transformlocvalues

一起使用
>>> df["size2"] = df["size"].loc[df.groupby("adult")["weight"].transform("idxmax")].values
>>> df
   adult size  weight size2
0  False    S       8     M
1  False    S      10     M
2  False    M      11     M
3  False    M       1     M
4  False    M      20     M
5   True    L      14     L
6   True    S      12     L

一步一步,首先我们找到合适的指数:

>>> df.groupby("adult")["weight"].transform("idxmax")
0    4
1    4
2    4
3    4
4    4
5    5
6    5
dtype: int64

然后我们使用这些索引到sizeloc

>>> df["size"].loc[df.groupby("adult")["weight"].transform("idxmax")]
4    M
4    M
4    M
4    M
4    M
5    L
5    L
Name: size, dtype: object

最后我们采用.values,以便在我们尝试分配时索引不会妨碍:

>>> df["size"].loc[df.groupby("adult")["weight"].transform("idxmax")].values
array(['M', 'M', 'M', 'M', 'M', 'L', 'L'], dtype=object)
>>> df["size2"] = df["size"].loc[df.groupby("adult")["weight"].transform("idxmax")].values
>>> df
   adult size  weight size2
0  False    S       8     M
1  False    S      10     M
2  False    M      11     M
3  False    M       1     M
4  False    M      20     M
5   True    L      14     L
6   True    S      12     L