pandas的转换不能对groupby输出进行排序

时间:2012-12-13 06:46:05

标签: python aggregate pandas

另一个熊猫问题。

阅读Wes Mckinney关于数据分析和熊猫的优秀书籍,我遇到了以下我认为应该有效的事情:

假设我有一些关于提示的信息。

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

足够好,但后来我想用pandas'变换来做同样的事情:

def top_all(df):
    return df.sort_index(by='tip_pct')

tips.groupby('smoker').transform(top_all)

但我得到了这个:

TypeError: Transform function invalid for data types

为什么呢?我知道转换需要返回一个它接受作为输入的相同维度的数组,所以我认为我只需要对原始DataFrame的两个切片(吸烟者和非吸烟者)进行排序而不改变它们各自的维度。谁能解释为什么失败了?

1 个答案:

答案 0 :(得分:50)

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['tip'])。这是一个例子:

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

您可以看到首先使用原始数据框的C = 1组的A列调用foo,然后是该组的B列,然后是C = 2组的A列等等。

如果您考虑变换是什么,这是有道理的。它意味着在组上应用变换函数。但总的来说,这些功能在应用于整个组时只会对给定的列有意义。例如,pandas docs中的示例是关于使用transform进行z标准化。如果你有一个包含年龄和体重列的DataFrame,那么就这两个变量的整体平均值而言,z标准化是没有意义的。它并不意味着要取一堆数字的总体平均值,其中一些是年龄,其中一些是权重。您必须根据平均年龄和相对于平均体重的权重对年龄进行z标准化,这意味着您需要为每个列单独进行转换。

所以基本上,你不需要在这里使用变换。 apply是适当的功能,因为apply确实作为单个DataFrame对每个组进行操作,而transform对每个组的每一列进行操作。