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

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

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

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

pandas

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

Q&A

解決済

2回答

928閲覧

特定の列の要素の個数を条件にして、新たな列を追加する方法について

upa0928

総合スコア1

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

pandas

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

0グッド

0クリップ

投稿2021/10/06 08:58

前提・実現したいこと

Anaconda, Jupyte Notebook環境でPythonの勉強をしています。
現在は読み込んだCSVファイルを元にDataFrameの様々な集計や加工を行っていますが、特定の条件で新たな列を追加する処理に苦戦しています。

元になるDataFrame(df)

ID分類フラグ
1A
1A
1A
1A
1B
2A
2A
2A
2A
2B

Dataframeに以下のような処理を行いたいと思います。

IDが同じグループの中で、分類がAの行についてフラグを参照し、

-前が3つ以上なら、同じIDのグループ全体にX
-後が3つ以上なら、同じIDのグループ全体にy
-それ以外なら、同じIDのグループ全体にz
として新たな列(新フラグ)追加する。

完成形のイメージとしては

ID分類フラグ新フラグ
1Ax
1Ax
1Ax
1Ax
1Bx
2Az
2Az
2Az
2Az
2Bz

発生している問題・エラーメッセージ

エラーまでたどり着けていません。

該当のソースコード

コードを書く前に、


-前が3つ以上なら、同じIDのグループ全体にX
-後が3つ以上なら、同じIDのグループ全体にy
-それ以外なら、同じIDのグループ全体にz
と判定する関数を作る。


「ID」「分類」でグループ化したdfに➀の関数を利用する。(グループごとに処理されることを期待)

という方針を立ててコードを書いてみたものの、よく考えたら「同じIDのグループ全体に結果を返したい」という実現したいことが全く取り込まれていない内容になってしまいました。

一応いま考えているコードを記載します。

Python

1#新フラグに何を入れるか判定する関数 2def decision(row): 3 4 if row['フラグ'].count('前').sum() >= 3 : 5 return 'x' 6 7 elif row['フラグ'].count('後').sum() >= 3 : 8 return 'y' 9 10 else: 11 return 'z' 12 13#dfに新フラグを追加 14df['新フラグ'] = df.groupby(['ID','分類'].agg(decision,axis=1) 15

試したこと

コードを書く以前にどういうロジックで処理を実現すればいいのか?の構想段階で止まってしまっています。

そもそもどのように考えればやりたいことが実現できるのかアドバイスをいただきたいです。(できればコード例もいただけると幸いです)

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

ここにより詳細な情報を記載してください。

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

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

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

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

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

guest

回答2

0

ベストアンサー

以下のような感じでよさそうです。

Python

1import pandas as pd 2from io import StringIO 3 4s = """ID,分類,フラグ 51,A,前 61,A,前 71,A,前 81,A,前 91,B,後 102,A,後 112,A,前 122,A,後 132,A,後 142,B,後""" 15df = pd.read_csv(StringIO(s)) 16 17def decision(df): 18 df = df[df['分類'] == 'A'] # 分類が'A'のみで絞る 19 if (df['フラグ'] == '前').sum() >= 3 : 20 return 'x' 21 elif (df['フラグ'] == '後').sum() >= 3 : 22 return 'y' 23 else: 24 return 'z' 25 26df2 = pd.DataFrame( [(id, decision(dfg)) for id, dfg in df.groupby(['ID'])], columns=['ID','新フラグ']) 27print(df2) 28# ID 新フラグ 29#0 1 x 30#1 2 y 31 32ret = df.merge(df2, on='ID') 33print(ret) 34""" 35 ID 分類 フラグ 新フラグ 360 1 A 前 x 371 1 A 前 x 382 1 A 前 x 393 1 A 前 x 404 1 B 後 x 415 2 A 後 y 426 2 A 前 y 437 2 A 後 y 448 2 A 後 y 459 2 B 後 y 46""" 47

投稿2021/10/06 12:36

can110

総合スコア38341

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

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

upa0928

2021/10/08 14:21

ありがとうございます! やりたいことが実現できました!
guest

0

groupbyとapplyとmergeを使うので、少し複雑になります。

python

1>>> print(df) 2 ID 分類 フラグ 30 1 A 前 41 1 A 前 52 1 A 前 63 1 A 前 74 1 B 後 85 2 A 後 96 2 A 前 107 2 A 後 118 2 A 後 129 2 B 後 13>>> 14>>> def classify(row): 15... if row['前'] >= 3: return 'X' 16... elif row['後'] >= 3: return 'Y' 17... else: return 'z' 18... 19>>> df2 = df.groupby(['ID','フラグ']).count().reset_index() 20>>> df3 = df2.pivot(index='ID', columns='フラグ') 21>>> df3.columns = ['前', '後'] 22>>> df3['新フラグ'] = df3.apply(classify, axis=1) 23>>> df_result = df3[['新フラグ']].merge(df, on='ID')[['ID', '分類', 'フラグ', '新フラグ']] 24>>> print(df_result) 25 ID 分類 フラグ 新フラグ 260 1 A 前 X 271 1 A 前 X 282 1 A 前 X 293 1 A 前 X 304 1 B 後 X 315 2 A 後 Y 326 2 A 前 Y 337 2 A 後 Y 348 2 A 後 Y 359 2 B 後 Y

投稿2021/10/06 09:34

ppaul

総合スコア24670

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

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

upa0928

2021/10/06 11:55

ご回答ありがとうございます! いったん何も考えずに自身のDataFrameを使っていただいたコードを打ち込んでみたのですがエラーになってしまいます。 理由としてあり得そうなのは、実際のデータでは他の列も存在するということです。 どういった状況でも同様のコードで実現できますでしょうか? また、 df2 = df.groupby(['ID','フラグ']).count().reset_index() こちらですが、IDとフラグではなく、IDと分類によるグループ化が必要な想定でしたが間違っていますでしょうか・・・?
upa0928

2021/10/06 12:11

また、私が実現したいこととしては indexの5~9はzになる想定です。
upa0928

2021/10/06 12:31

↑2つ目のコメントは間違いです。yで大丈夫でした。
ppaul

2021/10/06 23:18

df2 = df.groupby(['ID','フラグ']).count().reset_index() を df2 = df[['ID','分類','フラグ']].groupby(['ID','フラグ']).count().reset_index() に変更してください。 また df_result = df3[['新フラグ']].merge(df, on='ID')[['ID', '分類', 'フラグ', '新フラグ']] は並べ替えなので df_result = df3[['新フラグ']].merge(df, on='ID') としておいて、あとは必要な形に並べ替えてください。
upa0928

2021/10/08 14:21

ありがとうございます! やりたいことが実現できました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問