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

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

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

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

Python

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

Q&A

解決済

2回答

445閲覧

python groupby countした値を追加し、新たなカラムを作りたい

退会済みユーザー

退会済みユーザー

総合スコア0

Python 3.x

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

Python

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

0グッド

1クリップ

投稿2019/08/08 08:32

編集2019/08/09 03:02

実現したいこと

chanelデータをもとに、webのみ、店頭のみ、どちらも利用 に分けた新たなカラム(main_channel)を作りたい。

試したこと

pandasのgroupby関数を使用して、どうにか加工できないか模索している状況です。

希望のデータ構造

python

1import pandas as pd 2 3df = pd.DataFrame([[1,'2018-12-17','web','どちらも利用'], 4 [1,'2018-12-18','web','どちらも利用'], 5 [1,'2018-12-10','store','どちらも利用'], 6 [2,'2019-1-10','store','店頭のみ'], 7 [2,'2019-1-10','store','店頭のみ']], 8 columns=['no','sale_date','channel','main_channel']) 9 10# id sale_date channel main_channel 11# 1 2018-12-17 web どちらも利用 12# 1 2018-12-18 web どちらも利用 13# 1 2018-12-10 store どちらも利用 14# 2 2019-1-10 store 店頭のみ 15# 2 2019-1-10 store 店頭のみ

main_chanelの条件

どちらも利用:同idでchannelカラムにweb,storeが存在する。
店頭のみ:同idでchannelカラムにstoreのみが存在する。
webのみ:同IDでchannelカラムにwebのみが存在する。

### 発生するエラー

python

1 2pdf = pd.pivot_table(df.loc[:, ["no", "channel"]], index="no", 3 columns="channel", aggfunc=len) 4 5# > print(pdf) 6# channel store web 7# no 8# 1 1.0 2.0 9# 6 2.0 NaN 10# 22 NaN 2.0 11 12 13def conv_func(row): 14 if row["store"] > 0 and row["web"] > 0: 15 return "どちらも利用" 16 elif row["store"] > 0: 17 return "店頭のみ" 18 elif row["web"] > 0: 19 return "Webのみ" 20 else: 21 raise RuntimeError(str(row)) 22 23 24id_main_channel_dict = dict(pdf.apply(conv_func, axis=1)) # dict: ID -> main_channel 25 26out: 27KeyError: ('web', 'occurred at index 07562705') 28

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

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

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

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

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

guest

回答2

0

ベストアンサー

考えてみると意外と難問ですよね…

pd.pivot_table() でchannel毎の出現数を数えてから apply() などで変換していく、みたいな方法をまず思いつきました。
Pandas技は色々あるので、もっとエレガントな方法があるかもしれないです。

python

1import pandas as pd 2 3### 入力 4df = pd.DataFrame([[1, '2018-12-17', 'web'], 5 [1, '2018-12-18', 'web'], 6 [1, '2018-12-10', 'store'], 7 [6, '2019-1-10', 'store'], 8 [6, '2019-1-10', 'store'], 9 [22, '2019-1-13', 'web'], 10 [22, '2019-1-15', 'web'], 11 ], 12 columns=['no', 'sale_date', 'channel']) 13 14### 処理 15 16pdf = pd.pivot_table(df.loc[:, ["no", "channel"]], index="no", 17 columns="channel", aggfunc=len) 18 19# > print(pdf) 20# channel store web 21# no 22# 1 1.0 2.0 23# 6 2.0 NaN 24# 22 NaN 2.0 25 26 27def conv_func(row): 28 if row["store"] > 0 and row["web"] > 0: 29 return "どちらも利用" 30 elif row["store"] > 0: 31 return "店頭のみ" 32 elif row["web"] > 0: 33 return "Webのみ" 34 else: 35 raise RuntimeError(str(row)) 36 37 38id_main_channel_dict = dict(pdf.apply(conv_func, axis=1)) # dict: ID -> main_channel 39df["main_channel"] = df.apply(lambda cols: id_main_channel_dict[cols["no"]], axis=1) 40 41# > print(df) 42# no sale_date channel main_channel 43# 0 1 2018-12-17 web どちらも利用 44# 1 1 2018-12-18 web どちらも利用 45# 2 1 2018-12-10 store どちらも利用 46# 3 6 2019-1-10 store 店頭のみ 47# 4 6 2019-1-10 store 店頭のみ 48# 5 22 2019-1-13 web Webのみ 49# 6 22 2019-1-15 web Webのみ

投稿2019/08/08 14:38

mokemokechicken

総合スコア948

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

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

退会済みユーザー

退会済みユーザー

2019/08/09 02:55

mokemokechicken様 ご回答ありがとうございます。 大変参考になります。 別データで実行しようとしたところ、 id_main_channel_dict = dict(pdf.apply(conv_func, axis=1)) →このコードで、奇妙なエラーが出てしまいます。 KeyError: ('web', 'occurred at index 07562705') 何かご教授いただくことは可能でしょうか? 何卒宜しくお願い致します。
mokemokechicken

2019/08/09 03:03

うーん、なんでしょうね... KeyError だから dict へのアクセスでエラーになっている気はしますが、何かちょっと違和感のあるメッセージですね。 とりあえずは、conv_func の中で強気に row["store"], row["web"] としていますが、 row.get("store", 0) とか row.get("web", 0) とかしてみるとかですかね。 ※治る気もちょっとしないですが。 今回使った no=07562705 のデータが少し特殊なのかもしれませんね。 見てみて気がつくことはないでしょうか?
退会済みユーザー

退会済みユーザー

2019/08/13 02:09

mokemokechicken様 いつも丁寧にご回答いただき誠にありがとうございます。 無事、解決いたしました。 原因は、データ型の問題でした。 ※object型に数字と英字が同居していた mokemokechicken様のアドバイスがなければ、頓挫していたと思います。 groupbyでは実現できないと思うので、 本当にありがとうございました。
guest

0

存在する各IDに対して、
1.IDでフィルタをかける
2.channelの値をチェックする。
3.2の結果に応じてmain_channelに入力する。
といった方法になると思います。

DataFrame.groupbyだけで実現するのは難しいのではないでしょうか?

投稿2019/08/08 14:20

meg_

総合スコア10580

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問