🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Python 3.x

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

Python

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

Q&A

解決済

1回答

4278閲覧

pandas.DataFrameで日付カラムの月数差分を求めたい。rolling() relativedelta()

EM1206

総合スコア30

Python 3.x

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

Python

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

0グッド

0クリップ

投稿2019/12/09 11:14

編集2019/12/10 01:42

前提・実現したいこと

  • DataFrameの特定カラムに入っているTimeStampの月数差分を求めたい
  • 日数差分はdiff()で求められたが、差分が月を跨いでいるかを判定したい

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

以下のようなデータが有り、KOJI_NOでgroupbyしてYOTEI_YMDの差分(変化)を求めようとしています。
YOTEI_YMDをpd.to_datetime()してからdiff()で日数差分は求められました。
rolling()とrelativedelta()を組み合わせた関数で月数差分を求めようとしたのですが上手くいきません。
当該処理の実現方法がわかる方いましたら、ご教示いただきたく宜しくお願い致します。
↓元データ

OUTPUT_DAYKOJI_NOYOTEI_YMD
20191101A1234520190708
20191102A1234520190827
20191103A1234520190827
20191106A1234520190827
20191107A1234520190828
20191108A1234520190824
20191101B1234520190704
20191102B1234520190708
20191103B1234520190827
20191106B1234520190827
20191107B1234520190827
20191108B1234520190827

↓求めたいデータ(days_diffとmonths_diffをconcat(axis=1)で結合)

OUTPUT_DAYKOJI_NOYOTEI_YMDdays_diffmonths_diff
20191101A1234520190708NanNan
20191102A1234520190827501
20191103A123452019082700
20191106A123452019082700
20191107A123452019082810
20191108A1234520190824-40
20191101B1234520190704NanNan
20191102B123452019070840
20191103B123452019082700
20191106B123452019082700
20191107B123452019082700
20191108B123452019082700
DataError: No numeric types to aggregate

該当のソースコード

months_diffを求めるコードでエラーとなってしまします。

python

1import pandas as pd 2from dateutil import relativedelta as rdelta 3 4df['YOTEI_YMD'] = pd.to_datetime(df['YOTEI_YMD'], format='%Y%m%d') 5days_diff = df.groupby(['KOJI_NO'])['YOTEI_YMD'].diff() 6 7def func_diff_month(x): 8 m0, m1 = x[0], x[1] 9 return rdelta.relativedelta(m0, m1).months 10 11months_diff = df.groupby(['KOJI_NO'])['YOTEI_YMD'].rolling(2).apply(func_diff_month)

試したこと

rolling(2)の窓サイズの要素を、relativedelta().monthsで月数差分を取得しようとしました。

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

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

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

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

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

magichan

2019/12/10 01:12

申し訳ありませんが、上記のデータから出力したい理想とする結果を記載していただけませんでしょうか。
EM1206

2019/12/10 01:43

magichan様、求めたいデータフレームを追記しました。 ご確認のほど宜しくお願い致します。
guest

回答1

0

ベストアンサー

とりあえず書いてみましたが、やりたいことと合ってますでしょうか?

Python

1import pandas as pd 2import io 3 4csv = """ 5OUTPUT_DAY,KOJI_NO,YOTEI_YMD 620191101,A12345,20190708 720191102,A12345,20190827 820191103,A12345,20190827 920191106,A12345,20190827 1020191107,A12345,20190828 1120191108,A12345,20190824 1220191101,B12345,20190704 1320191102,B12345,20190708 1420191103,B12345,20190827 1520191106,B12345,20190827 1620191107,B12345,20190827 1720191108,B12345,20190827 18""" 19 20def calc_month(d): 21 shift_d = d.shift(1) 22 return (d.dt.year - shift_d.dt.year) * 12 + (d.dt.month - shift_d.dt.month) - (d.dt.day < shift_d.dt.day) 23 24df = pd.read_csv(io.StringIO(csv), parse_dates=['OUTPUT_DAY','YOTEI_YMD']) 25df['days_diff'] = df.groupby('KOJI_NO')['YOTEI_YMD'].apply(lambda d: (d-d.shift(1)).dt.days) 26df['monthss_diff'] = df.groupby('KOJI_NO')['YOTEI_YMD'].apply(calc_month) 27print(df) 28# OUTPUT_DAY KOJI_NO YOTEI_YMD days_diff monthss_diff 29#0 2019-11-01 A12345 2019-07-08 NaN NaN 30#1 2019-11-02 A12345 2019-08-27 50.0 1.0 31#2 2019-11-03 A12345 2019-08-27 0.0 0.0 32#3 2019-11-06 A12345 2019-08-27 0.0 0.0 33#4 2019-11-07 A12345 2019-08-28 1.0 0.0 34#5 2019-11-08 A12345 2019-08-24 -4.0 -1.0 35#6 2019-11-01 B12345 2019-07-04 NaN NaN 36#7 2019-11-02 B12345 2019-07-08 4.0 0.0 37#8 2019-11-03 B12345 2019-08-27 50.0 1.0 38#9 2019-11-06 B12345 2019-08-27 0.0 0.0 39#10 2019-11-07 B12345 2019-08-27 0.0 0.0 40#11 2019-11-08 B12345 2019-08-27 0.0 0.0

投稿2019/12/10 07:42

magichan

総合スコア15898

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

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

EM1206

2019/12/10 09:27

ご教示いただいた内容で、実現したい処理が出来ました。 rollingせずにshiftでずらしていく発想はありませんでした。 relativedelta()を使わずにdtで実現した点も応用がききそうです、ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問