23

別のパンダの質問。

Wes Mckinney の Data Analysis と Pandas に関する優れた本を読んでいると、うまくいくと思われる次のことに遭遇しました。

ヒントに関する情報があるとします。

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総請求額、つまり喫煙者と非喫煙者に分けて、5つの最大のヒントを知りたい. したがって、これは機能します:

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

なんで?変換は、入力として受け入れるのと同じ次元の配列を返す必要があることを知っているので、元の DataFrame の両方のスライス (喫煙者と非喫煙者) をそれぞれの次元を変更せずにソートするだけで、その要件に準拠していると思いました。 . 失敗した理由を説明できる人はいますか?

4

1 に答える 1

62

transform十分に文書化されていませんが、変換関数が渡されるのは、データフレームとしてのグループ全体ではなく、単一グループの単一列であることが機能するようです。あなたがやろうとしていることを本当に意味しているとは思いません。あなたの解決策applyは問題ありません。

そう仮定しますtips.groupby('smoker').transform(func)。group1 と group2 という 2 つのグループがあります。func(group1)変換はand を呼び出しません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.

foo最初に元のデータ フレームの C=1 グループの A 列だけで呼び出され、次にそのグループの B 列、次に C=2 グループの A 列などで呼び出されることがわかります。

これは、変換の目的を考えると理にかなっています。グループに変換関数を適用するためのものです。ただし、一般に、これらの関数はグループ全体に適用された場合には意味がなく、特定の列にのみ適用されます。たとえば、パンダのドキュメントの例は、を使用した z 標準化に関するものtransformです。年齢と体重の列を持つ DataFrame がある場合、これら両方の変数の全体的な平均に関して z 標準化することは意味がありません。年齢や体重など、さまざまな数値の全体的な平均をとっても意味がありません。平均年齢に関して年齢を z 標準化し、平均体重に関して体重を標準化する必要があります。つまり、列ごとに個別に変換する必要があります。

基本的に、ここでは変換を使用する必要はありません。 実際には各グループを単一の DataFrame として操作し、各グループの各列を操作するapplyため、ここでは適切な関数です。applytransform

于 2012-12-13T07:19:15.917 に答える