панды' преобразование не работает сортировка выходных данных метода groupBy
[5] Еще один вопрос панды.
Читая превосходную книгу Уэса Маккинни об анализе данных и пандах, я столкнулся со следующей вещью, которая, как мне казалось, должна была сработать:]}Предположим, у меня есть некоторая информация о советах.
In [119]:
tips.head()
Out[119]:
total_bill tip sex smoker day time size tip_pct
0 16.99 1.01 Female False Sun Dinner 2 0.059447
1 10.34 1.66 Male False Sun Dinner 3 0.160542
2 21.01 3.50 Male False Sun Dinner 3 0.166587
3 23.68 3.31 Male False Sun Dinner 2 0.139780
4 24.59 3.61 Female False Sun Dinner 4 0.146808
И я хочу знать пять самых больших чаевых по отношению к общему счету, то есть tip_pct
для курильщиков и некурящих отдельно. Итак, это работает:
def top(df, n=5, column='tip_pct'):
return df.sort_index(by=column)[-n:]
In [101]:
tips.groupby('smoker').apply(top)
Out[101]:
total_bill tip sex smoker day time size tip_pct
smoker
False 88 24.71 5.85 Male False Thur Lunch 2 0.236746
185 20.69 5.00 Male False Sun Dinner 5 0.241663
51 10.29 2.60 Female False Sun Dinner 2 0.252672
149 7.51 2.00 Male False Thur Lunch 2 0.266312
232 11.61 3.39 Male False Sat Dinner 2 0.291990
True 109 14.31 4.00 Female True Sat Dinner 2 0.279525
183 23.17 6.50 Male True Sun Dinner 4 0.280535
67 3.07 1.00 Female True Sat Dinner 1 0.325733
178 9.60 4.00 Female True Sun Dinner 2 0.416667
172 7.25 5.15 Male True Sun Dinner 2 0.710345
Достаточно хорошо, но тогда я хотел использовать преобразование панды, чтобы сделать то же самое, как это:
def top_all(df):
return df.sort_index(by='tip_pct')
tips.groupby('smoker').transform(top_all)
Но вместо этого я получаю следующее:
TypeError: Transform function invalid for data types
Почему? Я знаю, что преобразование требует возврата массива тех же измерений, которые оно принимает в качестве входных данных, поэтому я думал, что буду соответствовать этому требованию, просто сортируя оба среза (курильщиков и некурящих) исходного фрейма данных без изменения их соответствующих размеров. Может ли кто-нибудь объяснить, почему это не удалось?
1 ответ:
transform
это не так хорошо документировано, но кажется, что способ его работы заключается в том, что функция преобразования передается не всей группе как фрейму данных, а одному столбцу одной группы. Я не думаю, что это действительно предназначено для того, что вы пытаетесь сделать, и ваше решение сapply
прекрасно.Итак, предположим
tips.groupby('smoker').transform(func)
. Будет две группы, назовем их group1 и group2. Преобразование не вызываетfunc(group1)
иfunc(group2)
. Вместо этого он вызываетfunc(group1['total_bill'])
, затемfunc(group1['tip'])
и т. д., а затемfunc(group2['total_bill'])
,func(group2['total_bill'])
. Вот пример:>>> print d A B C 0 -2 5 4 1 1 -1 2 2 0 2 1 3 -3 1 2 4 5 0 2 >>> def foo(df): ... print ">>>" ... print df ... print "<<<" ... return df >>> print d.groupby('C').transform(foo) >>> 2 0 Name: A <<< >>> 2 2 Name: B <<< >>> 1 1 3 -3 4 5 Name: A <<< >>> 1 -1 3 1 4 0 Name: B # etc.
Вы можете видеть, что
Это имеет смысл, если вы подумаете о том, для чего предназначена трансформация. Он предназначен для применения функций преобразования к группам. Но в целом, эти функции не будут иметь смысла, когда применяются ко всей группе, только к данному столбцу. Например, пример в в pandas docs речь идет о Z-стандартизации с использованиемfoo
сначала вызывается только столбцом A группы C=1 исходного фрейма данных, затем столбцом B этой группы, затем столбцом A группы C=2 и т. д.transform
. Если у вас есть фрейм данных со столбцами для возраста и веса, не имеет смысла Z-стандартизировать по отношению к общему среднему значению обеих этих переменных. Это даже ничего не значит, если взять общее среднее из множества чисел, некоторые из которых являются возрастами, а некоторые-весами. Вы должны Z-стандартизировать возраст по отношению к среднему возрасту и вес по отношению к среднему весу, что означает, что вы хотите преобразовать отдельно для каждой колонки. Таким образом, в принципе, вам не нужно использовать преобразование здесь.apply
является здесь подходящей функцией, потому чтоapply
действительно оперирует с каждой группой как единым фреймом данных, в то время какtransform
оперирует с каждым столбцом каждой группы.