1. ホーム
  2. python

[解決済み] Pandasの集約関数で返されたカラムに名前を付ける?[重複)。

2022-04-29 02:01:01

質問

Pandasのgroupby機能で困っています。私は ドキュメント しかし、複数のカラムに集約関数を適用する方法がわかりません。 は、それらの列にカスタム名を付けています。

これは非常に近いですが、返されるデータ構造にはネストされた列見出しがあります。

data.groupby("Country").agg(
        {"column1": {"foo": sum()}, "column2": {"mean": np.mean, "std": np.std}})

(つまり、column2 の平均と標準を取りたいが、それらの列を "mean" と "std" として返したい)

何が足りないのでしょうか?

解決方法は?

パンダの場合 >= 0.25

返された集約カラムに名前を付ける機能が masterブランチに再導入されました。 で、pandas 0.25をターゲットにしています。新しい構文は .agg(new_col_name=('col_name', 'agg_func') . 詳細な例は、上記のリンク先のPRにあります。

In [2]: df = pd.DataFrame({'kind': ['cat', 'dog', 'cat', 'dog'],
   ...:                    'height': [9.1, 6.0, 9.5, 34.0],
   ...:                    'weight': [7.9, 7.5, 9.9, 198.0]})
   ...:

In [3]: df
Out[3]:
  kind  height  weight
0  cat     9.1     7.9
1  dog     6.0     7.5
2  cat     9.5     9.9
3  dog    34.0   198.0

In [4]: df.groupby('kind').agg(min_height=('height', 'min'), 
                               max_weight=('weight', 'max'))
Out[4]:
      min_height  max_weight
kind
cat          9.1         9.9
dog          6.0       198.0

また、この構文と私が以前提案した2段階のリネーム構文で、以下のように複数のラムダ式を使用することが可能になります。 このPR . ここでもPRにある例からコピーしています。

In [2]: df = pd.DataFrame({"A": ['a', 'a'], 'B': [1, 2], 'C': [3, 4]})

In [3]: df.groupby("A").agg({'B': [lambda x: 0, lambda x: 1]})
Out[3]:
         B
  <lambda> <lambda 1>
A
a        0          1

で、次に .rename() , または一回で。

In [4]: df.groupby("A").agg(b=('B', lambda x: 0), c=('B', lambda x: 1))
Out[4]:
   b  c
A
a  0  0


パンダの場合 < 0.25

現在受け入れられているunutbuによる回答は、pandasのバージョン <= 0.20でこれを行う素晴らしい方法を記述しています。しかし、pandas 0.20の時点で、この方法を使用すると、pandasの将来のバージョンでこの構文が使用できないことを示す警告が表示されます。

シリーズです。

<ブロッククオート

将来の警告: 集約のために Series で dict を使用することは非推奨であり、将来のバージョンで削除される予定です。

データフレーム

FutureWarning: リネームを伴うdictの使用は非推奨であり、将来のバージョンで削除される予定です。

によると pandas 0.20 changelog で、集計時に列の名前を変更する推奨方法は以下の通りです。

# Create a sample data frame
df = pd.DataFrame({'A': [1, 1, 1, 2, 2],
                   'B': range(5),
                   'C': range(5)})

# ==== SINGLE COLUMN (SERIES) ====
# Syntax soon to be deprecated
df.groupby('A').B.agg({'foo': 'count'})
# Recommended replacement syntax
df.groupby('A').B.agg(['count']).rename(columns={'count': 'foo'})

# ==== MULTI COLUMN ====
# Syntax soon to be deprecated
df.groupby('A').agg({'B': {'foo': 'sum'}, 'C': {'bar': 'min'}})
# Recommended replacement syntax
df.groupby('A').agg({'B': 'sum', 'C': 'min'}).rename(columns={'B': 'foo', 'C': 'bar'})
# As the recommended syntax is more verbose, parentheses can
# be used to introduce line breaks and increase readability
(df.groupby('A')
    .agg({'B': 'sum', 'C': 'min'})
    .rename(columns={'B': 'foo', 'C': 'bar'})
)

をご覧ください。 0.20 チェンジログ をご覧ください。

2017-01-03更新 @JunkMechanicさんのコメントに対応しました。

旧スタイルの辞書構文では、複数の lambda 関数に .agg というのは、渡された辞書のキーを使って名前が変更されるからです。

>>> df.groupby('A').agg({'B': {'min': lambda x: x.min(), 'max': lambda x: x.max()}})

    B    
  max min
A        
1   2   0
2   4   3

複数の関数をリストとして1つのカラムに渡すことも可能です。

>>> df.groupby('A').agg({'B': [np.min, np.max]})

     B     
  amin amax
A          
1    0    2
2    3    4

しかし、ラムダ関数は匿名であり、すべて <lambda> となり、名前の衝突が発生します。

>>> df.groupby('A').agg({'B': [lambda x: x.min(), lambda x: x.max]})
SpecificationError: Function names must be unique, found multiple named <lambda>

を回避するために SpecificationError を使用する代わりに、名前付き関数を事前に定義することができます。 lambda . また、適切な関数名により .rename を後からデータフレームに追加することができます。これらの関数は、上記と同じリスト構文で渡すことができます。

>>> def my_min(x):
>>>     return x.min()

>>> def my_max(x):
>>>     return x.max()

>>> df.groupby('A').agg({'B': [my_min, my_max]})

       B       
  my_min my_max
A              
1      0      2
2      3      4