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

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

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

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

Python

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

pandas

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

Q&A

解決済

1回答

1893閲覧

Pandas1.0.1のDataFrame.groupby.rolling.apply()の挙動について

EM1206

総合スコア30

Python 3.x

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

Python

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

pandas

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

0グッド

1クリップ

投稿2020/03/18 04:55

前提

pandas0.25.1で実行できていたコードがpandas1.0.1で正常実行できるか確認していますが
DataFrame.groupby.rolling.apply()しているコードでKeyErrorが発生しています。

pandas1.0以降に知見ある方いましたら、アドバイスいただけると助かります。

実現したいこと

以下のような発注データに対して'Order_no'でgroupby()して前回の発注データとの営業日数の差分を
'Order_date'から算出、returnする。
※pandas0.25.1では問題なく動作していた。

Order_noOrder_date
0A000120200201
2A000120200203
1A000120200205
3B000120200201
6B000120200202
4B000120200203
5B000120200204
7C000120200202
8C000120200205
9C000120200205
10C000120200208
11C000120200209
### 発生している問題・エラーメッセージ
pandas1.0.1
```
KeyError: 0
pandas0.25.1のFutureWarning

FutureWarning:
Currently, 'apply' passes the values as ndarrays to the applied function.
In the future, this will change to passing it as Series objects.
You need to specify 'raw=True' to keep the current behaviour,
and you can pass 'raw=False' to silence this warning
test = df.groupby(['Order_no'])['Order_date'].rolling(2).apply(calc_diff)

### 該当のソースコード ```python import pandas as pd dict1 = dict(Order_no=['A0001','A0001','A0001','B0001','B0001','B0001', 'B0001','C0001','C0001','C0001','C0001','C0001'], Order_date=[20200201,20200205,20200203,20200201,20200203, 20200204,20200202,20200202,20200205,20200205, 20200208,20200209]) df = pd.DataFrame(dict1).sort_values(['Order_no','Order_date']) #関数のif文内では実際は所定カレンダーと付け合わせて営業日数の細分をreturnします def calc_diff(d): d1, d2 = int(d[0]), int(d[1]) if d1 == d2: return 0 elif d1 < d2: return 1 diff = df.groupby(['Order_no'])['Order_date'].rolling(2).apply(calc_diff)

試したこと

groupby()を外した場合は問題なく実行できました。

グルーピングした場合に
calc_diff内のd1, d2 = int(d[0]), int(d[1])で変数に値が渡せていないようです。

FutureWarningと公式ドキュメントを参考に以下のコードも試したがダメでした。
df.groupby(['Order_no'])['Order_date'].rolling(2).apply(calc_diff,raw=True)

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

Python 3.7.6
pandas 1.0.1

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

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

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

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

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

guest

回答1

0

ベストアンサー

まず、エラーの原因ですが、pandas 1.0.0 での

https://pandas.pydata.org/pandas-docs/version/1.0.0/whatsnew/v1.0.0.html

  • Changed the default value for the raw argument in Series.rolling().apply(), DataFrame.rolling().apply(), Series.expanding().apply(), and DataFrame.expanding().apply() from None to False (GH20584)

の変更でしょうね。

この変更により、デフォルトで (raw=None :Trueの場合と同じ挙動) データが ndarray で渡されるていがのが、デフォルト値が raw=False になったため、データが Series型で渡されている ために

Python

1 d1, d2 = int(d[0]), int(d[1])

の部分でエラーとなっているようです。
データがSeries型の時に動作させるなら、単純にこの部分を

Python

1 d1, d2 = int(d.iat[0]), int(d.iat[1])

に変更すると動作すると思われますが、pandas のバージョンに関わらずに動作させるためには やはり raw パラメータを明示的に raw=True としたいところです。

が、私の環境でも EM1206さんの環境と同じく raw=True を指定してもデータは Series型で渡されているようです。(ソースコードを追っていないのですが、バグなのかもしれません)

pandas 1.0.2 でどうしても raw=True を使いたいのであれば、同じく 1.0.0 からの新機能である、enginnumba を指定する(engine='numba'をパラメータに追加)ことで、raw=True が動作するようですので、こちらのパラメータを設定するのもありかもしれません (nunbaインストールが必要ですが)

https://pandas.pydata.org/pandas-docs/version/1.0.0/user_guide/computation.html#stats-rolling-apply

投稿2020/03/18 08:37

magichan

総合スコア15898

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

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

EM1206

2020/03/19 00:15

mugichanさん、ご回答いただきありがとうございます。 手元で確認しましたが以下のコードでpandas1.0.1で期待している結果を得られることができました。 d1, d2 = int(d.iat[0]), int(d.iat[1]) しかし、ご指摘の通り明示的にraw=Trueにしたくengine='numba'を試しました。 結果、以下のErrorが出てしまいました。 TypeError: expected int64, got None 私も検証を続けてみます。 もし他に気づきがありましたら、ご教示いただけると幸いです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問