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

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

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

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

pandas

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

Q&A

解決済

Python 時系列IDデータのDataFrameで月別の新規率を算出したい

pipilog2
pipilog2

総合スコア2

Python

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

pandas

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

1回答

0グッド

0クリップ

186閲覧

投稿2023/02/02 13:04

実現したいこと

pythonで下記のようなpandas DataFrameがあり、月ごとにどれくらいの顧客が購入したか、新規人数&新規率をまとめたいです。
例えば、2021/1/1は ID:90,80,70の人が新規で購入したため、
3/5で60%、以降、1年間その人たちはリピーター。
1年間買い物がないと次の買い物時に新規とカウントする。なので、ID90の人は 2022/5/1で新規とカウント

ID month value
90 2021/1/1 930
90 2022/2/1 590
90 2022/5/1 240
80 2021/1/1 930
80 2022/4/1 980
80 2022/6/1 980
70 2021/1/1 980
70 2021/7/1 970
70 2021/8/1 950
40 2021/9/1 1020
40 2021/10/1 1140
30 2021/11/1 550
30 2021/12/1 890
30 2022/3/1 1110

該当のソースコード

python

1df = pd.DataFrame( 2 data={"ID":[90,90,90,80,80,80,70,70,70,40,40,30,30,30], 3 "month":["2021-01-01","2022-02-01","2022-05-01","2021-01-01","2022-04-01","2022-06-01","2021-01-01","2021-07-01","2021-08-01", 4"2021-09-01","2021-10-01","2021-11-01","2021-12-01","2022-03-01"], 5"value":[930,590,240,930,980,980,980,970,950,1020,1140,550,890,1110,]} 6) 7 8df

試したこと

なかなか実現するコードが思いつかず、ご教示いただけますと幸いです。
最終的にやりたいことは下記のようなイメージです。

month 新規人数 新規率 リピート人数 リピート率
2021/1/1 2 50% 1 10%
2021/7/1 1 40% 2 20%
2021/8/1 1 60% 2 30%
2021/9/1 2 100%3 30%
2021/10/1 1 10% 3 10%
2021/11/1 1 50% 1 20%

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

jupyter notebook

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

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

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

下記のような質問は推奨されていません。

  • 質問になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

適切な質問に修正を依頼しましょう。

回答1

0

ベストアンサー

1年間買い物がないと次の買い物時に新規とカウントする。なので、ID90の人は 2022/5/1で新規とカウント

※ おそらく、「ID90の人は『2022/2/1』で新規とカウント」かと思います。

python

1import pandas as pd 2 3df = pd.DataFrame( 4 data={"ID":[90,90,90,80,80,80,70,70,70,40,40,30,30,30], 5 "month":["2021-01-01","2022-02-01","2022-05-01","2021-01-01","2022-04-01","2022-06-01","2021-01-01","2021-07-01","2021-08-01", 6"2021-09-01","2021-10-01","2021-11-01","2021-12-01","2022-03-01"], 7"value":[930,590,240,930,980,980,980,970,950,1020,1140,550,890,1110,]} 8) 9 10df['month'] = pd.to_datetime(df['month']).dt.date 11nid = df['ID'].unique().size 12dfx = df.assign( 13 repeat = df.apply(lambda x: 14 x['ID'] in df.loc[df['month'].between((x['month'] - pd.DateOffset(years=1)).date(), 15 x['month'], inclusive='neither'), 'ID'].values, axis=1))\ 16 .groupby('month').agg( 17 新規人数 = ('repeat', lambda x: (~x).sum()), 18 新規率 = ('repeat', lambda x: f'{(~x).sum()*100/nid}%'), 19 リピート人数 = ('repeat', 'sum'), 20 リピート率 = ('repeat', lambda x: f'{x.sum()*100/nid}%'))\ 21 .reset_index() 22 23print(dfx)
month新規人数新規率リピート人数リピート率
2021-01-01360.0%00.0%
2021-07-0100.0%120.0%
2021-08-0100.0%120.0%
2021-09-01120.0%00.0%
2021-10-0100.0%120.0%
2021-11-01120.0%00.0%
2021-12-0100.0%120.0%
2022-02-01120.0%00.0%
2022-03-0100.0%120.0%
2022-04-01120.0%00.0%
2022-05-0100.0%120.0%
2022-06-0100.0%120.0%

投稿2023/02/02 15:12

melian

総合スコア17151

下記のような回答は推奨されていません。

  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

回答へのコメント

pipilog2

2023/02/03 00:09

melian 様 ありがとうございました。実現できました。 まったく思いもつかないコードでした。

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

ただいまの回答率
86.02%

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

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

質問する

関連した質問

同じタグがついた質問を見る

Python

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

pandas

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