Python Pandas: как добавить совершенно новый столбец во фрейм данных внутри операции группировки/преобразования

Я хочу отметить некоторые квантили в своих данных, и для каждой строки DataFrame я хотел бы, чтобы запись в новом столбце называлась, например. "xtile" для хранения этого значения.

Например, предположим, что я создаю фрейм данных следующим образом:

import pandas, numpy as np
dfrm = pandas.DataFrame({'A':np.random.rand(100), 
                         'B':(50+np.random.randn(100)), 
                         'C':np.random.randint(low=0, high=3, size=(100,))})

И допустим, я пишу свою собственную функцию для вычисления квинтиля каждого элемента в массиве. У меня есть для этого своя функция, но, например, просто обратитесь к scipy.stats.mstats.mquantile.

import scipy.stats as st
def mark_quintiles(x, breakpoints):
    # Assume this is filled in, using st.mstats.mquantiles.
    # This returns an array the same shape as x, with an integer for which
    # breakpoint-bucket that entry of x falls into.

Теперь реальный вопрос заключается в том, как использовать transform для добавления нового столбца к данным. Что-то вроде этого:

def transformXtiles(dataFrame, inputColumnName, newColumnName, breaks):
    dataFrame[newColumnName] = mark_quintiles(dataFrame[inputColumnName].values, 
                                              breaks)
    return dataFrame

А потом:

dfrm.groupby("C").transform(lambda x: transformXtiles(x, "A", "A_xtile", [0.2, 0.4, 0.6, 0.8, 1.0]))

Проблема в том, что приведенный выше код не добавит новый столбец «A_xtile». Он просто возвращает мой фрейм данных без изменений. Если я сначала добавлю столбец, полный фиктивных значений, таких как NaN, с именем "A_xtile", то он действительно успешно перезапишет этот столбец, чтобы включить правильные отметки квинтиля.

Но крайне неудобно сначала писать в графу о чем-то подобном, что я, возможно, захочу добавить на лету.

Обратите внимание, что простой apply здесь не сработает, поскольку он не будет знать, как разобраться в массивах результатов, возможно, разного размера для каждой группы.


person ely    schedule 12.09.2012    source источник
comment
Нет. Пожалуйста, посмотрите библиотеку Pandas.   -  person ely    schedule 12.09.2012
comment
Это жутко похоже на вопрос, который я как раз собирался задать! Странный!   -  person smci    schedule 21.03.2013


Ответы (1)


С какими проблемами вы сталкиваетесь при работе с apply? Это работает для этого игрушечного примера здесь, и длины групп разные:

In [82]: df
Out[82]: 
   X         Y
0  0 -0.631214
1  0  0.783142
2  0  0.526045
3  1 -1.750058
4  1  1.163868
5  1  1.625538
6  1  0.076105
7  2  0.183492
8  2  0.541400
9  2 -0.672809

In [83]: def func(x):
   ....:     x['NewCol'] = np.nan
   ....:     return x
   ....: 

In [84]: df.groupby('X').apply(func)
Out[84]: 
   X         Y  NewCol
0  0 -0.631214     NaN
1  0  0.783142     NaN
2  0  0.526045     NaN
3  1 -1.750058     NaN
4  1  1.163868     NaN
5  1  1.625538     NaN
6  1  0.076105     NaN
7  2  0.183492     NaN
8  2  0.541400     NaN
9  2 -0.672809     NaN
person Chang She    schedule 12.09.2012
comment
Он должен быть достаточно умным, чтобы автоматически знать, куда вставлять части этого нового столбца, относящиеся к группе. По сути, синтаксис df["NewCol"] = df.groupby("X").apply(some_inline_func) должен быть аналогичен определению some_inline_func таким же образом, как вы определили func выше. - person ely; 12.09.2012
comment
Как насчет: dfrm['A_xtile'] = dfrm.groupby('C').A.transform(mark_quintiles, [0.2, 0.4, 0.6, 0.8, 1.0])? (Кажется, работает на последней версии панд, не пробовал старые) - person Chang She; 13.09.2012
comment
Это превосходно и заслуживает того, чтобы быть в документе pandas Split-Apply-Combine Я только что провел 4 дня, пытаясь использовать set_index, sort_index и т. д., чтобы повторно вставить результат groupby обратно в исходный фрейм данных. - person smci; 03.05.2013
comment
@ChangShe, когда я пытаюсь df.groupby('X').apply(func), результирующий фрейм данных теперь индексируется выполненными группировками. Почему ваш так себя не ведет? - person guy; 20.07.2017
comment
@guy Добавьте group_keys=False в качестве аргумента в groupby - person cs95; 22.01.2019