另一个熊猫问题。
阅读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的两个切片(吸烟者和非吸烟者)进行排序而不改变它们各自的维度。谁能解释为什么失败了?
答案 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
对每个组的每一列进行操作。