質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.47%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

pandas

Pandasは、PythonでRにおけるデータフレームに似た型を持たせることができるライブラリです。 行列計算の負担が大幅に軽減されるため、Rで行っていた集計作業をPythonでも比較的簡単に行えます。 データ構造を変更したりデータ分析したりするときにも便利です。

Q&A

解決済

2回答

245閲覧

Pandas groupby時に、文字列が同じ場合は結合せずにそのままにしたい+グルーピングの個数を追加したい

kanchiru

総合スコア3

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

pandas

Pandasは、PythonでRにおけるデータフレームに似た型を持たせることができるライブラリです。 行列計算の負担が大幅に軽減されるため、Rで行っていた集計作業をPythonでも比較的簡単に行えます。 データ構造を変更したりデータ分析したりするときにも便利です。

1グッド

0クリップ

投稿2024/03/16 04:57

編集2024/03/17 03:36

実現したいこと

以下の2つの処理をしたいと考えています。

質問(1)

Python Pandas Dataframeを使って、データ1を下記のような条件でデータ2のようにまとめたい(データ1→データ2)

  • ID1とID2でグルーピングしたい
  • 数字はsumしたい
  • 文字列は結合したい(できれば「+」をつけたい)
  • ただし、文字列が同じ場合は結合せず1つだけにする

さらに、可能なら

  • ID2だけ文字列と同じ扱いにしたい。
  • もしそれが困難な場合は、ID2は使わないので、sumしてしまってもよい

(蛇足な質問です。先に、数字でなく文字列(dataframeの型を文字に)にすれば良いかもしれませんが、Pandasの使い方として、列ごとに指定できるか知りたいと思います)

質問(2)

さらに、種類1、種類2でグルーピングし、そのさいにまとめた時の個数と値1、値2にそれぞれ個数をかけた合計値1、合計値値2を追加したい(データ2→データ3)
(グルーピング時に、種類2名、値1、値2は同じなので、そのまま)

以上、よろしくお願い致します。

データ1

ID1ID2種類1種類2種類2名値1値2
D0011S02P0011337
D0011S03P001628
D0011S05P001220
D0012S02P002三角1010
D0012S05P002三角56
D0013S02P003四角1111
D0021S02P0041512
D0021S03P00498
D0031S02P002三角1010
D0031S06P002三角23
D0032S02P002三角1010
D0032S05P002三角56
D0033S01P00511

データ2

ID1ID2種類1種類2種類2名値1値2
D0011S02+S03+S05P0012185
D0012S02+S05P002三角1516
D0013S02P003四角1111
D0021S02+S03P0042420
D0031S02+S06P002三角1213
D0032S02+S05P002三角1516
D0033S01P00611

データ3

種類1種類2種類2名値1値2個数合計値1合計値2
S02+S03+S05P001218512185
S02+S05P002三角151623032
S02P003四角111111111
S02+S03P004242012420
S02+S06P002三角121311213
S01P00611111

該当のソースコード

質問(1)について

python

1# 本来はcsvを読み込んでいます。それにあわせるために、astype(int)しました。 2import pandas as pd 3 4df = pd.DataFrame([ 5['D001','1','S02','P001','丸','13','37'], 6['D001','1','S03','P001','丸','6','28'], 7['D001','1','S05','P001','丸','2','20'], 8['D001','2','S02','P002','三角','10','10'], 9['D001','2','S05','P002','三角','5','6'], 10['D001','3','S02','P003','四角','11','11'], 11['D002','1','S02','P004','線','15','12'], 12['D002','1','S03','P004','線','9','8'], 13['D003','1','S02','P002','三角','10','10'], 14['D003','1','S06','P002','三角','2','3'], 15['D003','2','S02','P002','三角','10','10'], 16['D003','2','S05','P002','三角','5','6'], 17['D003','3','S01','P005','丸','1','1'] 18], 19columns=['ID1','ID2','種類1','種類2','種類2名','値1','値2'], 20) 21 22df['ID2'] = df['ID2'].astype(int) 23df['値1'] = df['値1'].astype(int) 24df['値2'] = df['値2'].astype(int) 25 26dfg = df.groupby(['ID1','ID2']).sum() 27print(dfg)

発生している問題

質問(1)について

ID1ID2種類1種類2種類2名値1値2
D0011S02S03S05P001P001P001丸丸丸2185

sumだけですと、文字列も結合されてしまいます。
グルーピングのさい、同一の場合は、1つだけにしたいのですが、その方法が分かりません。

補足情報(FW/ツールのバージョンなど)

Python 3.12.1
pandas 2.1.4

melian👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

カラム毎に集計方式を変える方法を使えます。
公式ドキュメント
既定以外の集約方法の指定
https://pandas.pydata.org/docs/user_guide/groupby.html#aggregation-with-user-defined-functions
カラムごとに集約方法を変える
https://pandas.pydata.org/docs/user_guide/groupby.html#named-aggregation

使うとこんな感じですかね。

python

1# 本来はcsvを読み込んでいます。それにあわせるために、astype(int)しました。 2import pandas as pd 3 4df = pd.DataFrame([ 5['D001','1','S02','P001','丸','13','37'], 6# 略 7['D003','3','S01','P005','丸','1','1'] 8], 9columns=['ID1','ID2','種類1','種類2','種類2名','値1','値2'], 10) 11 12def agg_for_str(x): 13 return "+".join(set(x)) 14 15dfg = df.groupby(['ID1','ID2']).agg( 16 種類1=pd.NamedAgg(column="種類1", aggfunc=agg_for_str), 17 種類2=pd.NamedAgg(column="種類2", aggfunc=agg_for_str), 18 種類2=pd.NamedAgg(column="種類2名", aggfunc=agg_for_str), 191=pd.NamedAgg(column="値1", aggfunc="sum"), 202=pd.NamedAgg(column="値2", aggfunc="sum") 21) 22print(dfg)

投稿2024/03/16 06:02

TakaiY

総合スコア12774

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kanchiru

2024/03/16 06:19 編集

ご回答ありがとうございます。 質問(1)は解決いたしました。 カラムごとに集約方法を変える方法が行数は増えますが、直感的でした。 まずは、この方法で基本をおさえることができました。 さらにこの結果を処理する質問(2)のほうも教えていただければ幸いです。 よろしくお願い致します。
TakaiY

2024/03/16 07:04

できたdfgを再集計すればいいだけですが、何がわからないのでしょう?
guest

0

ベストアンサー

質問(1)
Python Pandas Dataframeを使って、データ1を下記のような条件でデータ2のようにまとめたい(データ1→データ2)

python

1agg_method = {'int64': 'sum', 'object': lambda x: '+'.join(x.unique())} 2type_method = {k: agg_method[str(v)] for k, v in df.iloc[:, 2:].dtypes.items()} 3dfx = df.groupby(['ID1','ID2'], as_index=False).agg(type_method) 4 5print(dfx)
ID1ID2種類1種類2種類2名値1値2
D0011S02+S03+S05P0012185
D0012S02+S05P002三角1516
D0013S02P003四角1111
D0021S02+S03P0042420
D0031S02+S06P002三角1213
D0032S02+S05P002三角1516
D0033S01P00511

質問(2)
さらに、種類1、種類2でグルーピングし、そのさいにまとめた時の個数と値1、値2にそれぞれ個数をかけた合計値1、合計値値2を追加したい(データ2→データ3)
(グルーピング時に、種類2名、値1、値2は同じなので、そのまま)

python

1grp = dfx.iloc[:,2:].groupby(['種類1', '種類2'], as_index=False, sort=False) 2dfy = grp.first() 3dfy['個数'] = grp.size()['size'] 4dfy['合計値1'] = dfy['値1'] * dfy['個数'] 5dfy['合計値2'] = dfy['値2'] * dfy['個数'] 6 7print(dfy)
種類1種類2種類2名値1値2個数合計値1合計値2
S02+S03+S05P001218512185
S02+S05P002三角151623032
S02P003四角111111111
S02+S03P004242012420
S02+S06P002三角121311213
S01P00511111

投稿2024/03/16 05:48

編集2024/03/16 07:04
melian

総合スコア19825

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kanchiru

2024/03/16 06:18

ご回答ありがとうございます。 質問(1)は解決いたしました。 ・少しこったことになる場合はagg()を使う ・sumしたくない場合は、範囲を限定する(df.iloc) ・groupbyでindexにならないようにする(as_index=False)も気づきです。 さらにこの結果を処理する質問(2)のほうも教えていただければ幸いです。 よろしくお願い致します。
kanchiru

2024/03/16 07:37

質問(2) ご回答ありがとうございます。 しかし、 TypeError: <lambda>() got an unexpected keyword argument 'include_groups' とでて実行できませんでした。 include_groupsを除くと実行できました。 pandasのドキュメントをみると、のぞいてしまっても問題なさそうですが、 どのような影響があるのでしょうか?
melian

2024/03/16 07:40

apply() を使わない方法に書き換えましたので、そちらでお試しください。
kanchiru

2024/03/16 07:51

種類1 種類2 種類2名 値1 値2 が同じことを利用ですね。 実現方法が本当にいろいろあります。 以上、すべて解決しました。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.47%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問