LoginSignup
10
8

More than 5 years have passed since last update.

PandasでDataFrameGroupByに対する列追加の処理は?

Posted at

GroupByした後に集約処理以外の普通のスキャン処理をやるのに標準の方法は無いようです。列を追加するにもDataFrameGroupByオブジェクトにそのままmulti indexで列結合する方法は面倒です。

以下のようなデータフレームに対して、集約以外のグループごとの処理を書いて、さらに列に追加する方法を整理しました。

df = pd.DataFrame({'group' : [1,1,2,3,3,3,3,2,2,4,4,4] , 'value' : [1,2,1,1,3,2,4,2,1,3,2,1]} )
    group  value
0       1      1
1       1      2
2       2      1
3       3      1
4       3      3
5       3      2
6       3      4
7       2      2
8       2      1
9       4      3
10      4      2
11      4      1

基本的にグループ化前のdfにグループ化→処理→フラット化した結果を代入するというのが素直な方法のようです。関数内で列を追加する方法もあるようですが。

DataFrameGroupByに対応した関数

以下のような場合は、特にそのまま関数を使えばよさそうです。

df['new'] = df.groupby('group')['value'].cumcount()

    group  value  new
0       1      1    0
1       1      2    1
2       2      1    0
3       3      1    0
4       3      3    1
5       3      2    2
6       3      4    3
7       2      2    1
8       2      1    2
9       4      3    0
10      4      2    1
11      4      1    2
df['new'] = df.groupby('group')['value'].rank()

    group  value  new
0       1      1  1.0
1       1      2  2.0
2       2      1  1.5
3       3      1  1.0
4       3      3  3.0
5       3      2  2.0
6       3      4  4.0
7       2      2  3.0
8       2      1  1.5
9       4      3  3.0
10      4      2  2.0
11      4      1  1.0

groupごとに行われることは暗黙のうちになされ、結果はフラット化されるようです。

DataFrameGroupByに対応しない関数をrow-wiseに処理したいとき

これは、特に特筆することはないですがapplyで可能です。

df['new'] = df.groupby('group')['value'].apply(lambda x:x+1)

    group  value  new
0       1      1    2
1       1      2    3
2       2      1    2
3       3      1    2
4       3      3    4
5       3      2    3
6       3      4    5
7       2      2    3
8       2      1    2
9       4      3    4
10      4      2    3
11      4      1    2

これも結果はフラット化されます。ただし、あくまでもgroup化されたSeriesに対して行っていますが、row-wiseではそれは意識することはないでしょう。

DataFrameGroupByに対応しない関数をgroup-wiseに処理したいとき

例えば、group化されたSeriesごとに直前の値との差分をとるような以下の関数の結果を見ると、グループごとに処理されていることがわかります。

df['new'] = df.groupby('group')['value'].apply(lambda y : y - y.shift() )

    group  value  new
0       1      1  NaN
1       1      2  1.0
2       2      1  NaN
3       3      1  NaN
4       3      3  2.0
5       3      2 -1.0
6       3      4  2.0
7       2      2  1.0
8       2      1 -1.0
9       4      3  NaN
10      4      2 -1.0
11      4      1 -1.0

同じく結果はフラット化されます。

もう少しシンプルな方法もあるのでしょうか?

10
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
8