2016-03-03 2 views
4

У меня есть следующие игрушки dataframe (реальная один имеет 500K строк):Панды: Назначают результат GroupBy к dataframe в новый столбец

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 

И хотите GroupBy 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']) 
+1

Я не понимаю, чего вы хотите. Вы хотите создать новый столбец 'size2' со значением в столбце' size2' ... – bozdoz

ответ

3

IIUC вы можете использовать merge. Я думаю, что первое значение в size2 - M, потому что max weight - 20.

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 
0

Просто более подробное veresion из @jazrael ответа, с dataframe:

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()] 

GroupBy на ' взрослый "будет производить серию с False, 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 
+0

С точки зрения производительности эта шкала решений? каков размер диапазона или df? – user3313834

1

Вы можете использовать transform с loc и values:

>>> 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 

Затем мы используем их, чтобы индекс в size колонку с loc:

>>> 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 
Смежные вопросы