PDEP-4: 一貫性のあるdatetimeパース
- 作成日: 2022年9月18日
- ステータス: 実装済み
- ディスカッション: #48621
- 作成者: Marco Gorelli
- 改訂版: 2
概要
提案内容は以下のとおりです。
to_datetime
が厳密になり、入力のすべての要素を同じdatetime形式でパースする。形式は、(ユーザーがformat
を指定しない場合)最初の非NaN要素から推測されるか、format
から取得される。infer_datetime_format
は非推奨となる(厳密なバージョンがデフォルトになるため)。- 非厳密なパースのための簡単な回避策が明確に文書化される。
動機と範囲
Pandasの日付パースは非常に柔軟だが、おそらく柔軟すぎる - https://github.com/pandas-dev/pandas/issues/12585 と関連するissueを参照して、これがどれだけの混乱を引き起こしているかを確認してください。Pandasは途中でフォーマットを切り替えることができ、これは文書化されているものの、ユーザーの期待を裏切る事が頻繁にあります。
簡単な例
In [1]: pd.to_datetime(['12-01-2000 00:00:00', '13-01-2000 00:00:00'])
Out[1]: DatetimeIndex(['2000-12-01', '2000-01-13'], dtype='datetime64[ns]', freq=None)
ユーザーはほぼ確実に、このデータを「1月12日、1月13日」として読み込もうとしていました。しかし、「12月1日、1月13日」として読み込まれます。警告やエラーは表示されません。
現在、一貫したパースを保証する唯一の方法は、明示的にformat=
を渡すことです。引数infer_datetime_format
は厳密ではなく、format
と一緒に呼び出すことができ、それでもユーザーの期待を裏切る可能性があります。
In [2]: pd.to_datetime(['12-01-2000 00:00:00', '13-01-2000 00:00:00'], infer_datetime_format=True)
Out[2]: DatetimeIndex(['2000-12-01', '2000-01-13'], dtype='datetime64[ns]', freq=None)
詳細な説明
具体的には、提案は以下のとおりです。
format
が指定されていない場合、pandasは最初の非NaN行から形式を推測し、その形式に従って残りの入力をパースします。エラーはerrors
引数に従って処理されます - 形式が黙って切り替わることはありません。infer_datetime_format
は非推奨となります。dayfirst
とyearfirst
は現在どおり機能し続けます。- 最初の非NaN行から形式を推測できない場合、
UserWarning
が表示され、ユーザーに明示的に形式を渡すよう促します。これは、'a'
(後でParserError
をスローする)や'00:12:13'
(現在'2022-09-18 00:12:13'
に変換される)など、無効な入力に対してのみ発生するはずです。
ユーザーが日付を混合形式で持っている場合、柔軟なパースを使用し、それが伴うリスクを受け入れることができます。例:
In [3]: pd.to_datetime(['12-01-2000 00:00:00', '13-01-2000 00:00:00'], format='mixed')
Out[3]: DatetimeIndex(['2000-12-01', '2000-01-13'], dtype='datetime64[ns]', freq=None)
または、日付がすべてISO8601形式の場合:
In [4]: pd.to_datetime(['2020-01-01', '2020-01-01 03:00'], format='ISO8601')
Out[4]: DatetimeIndex(['2020-01-01 00:00:00', '2020-01-01 03:00:00'], dtype='datetime64[ns]', freq=None)
使用方法と影響
私の予想では、影響は正味プラスになるでしょう。
- 潜在的に深刻なバグが早期に検出されます。
- 実際に混合形式を望んでいるユーザーは引き続きパースできますが、今度はそのことを非常に明確に示す必要があります。
- コードベースが大幅に簡素化されます。
私の知る限り、バグが導入される可能性はありません。
実装
whatsnewの記述は以下のとおりです。
次のメジャーバージョンリリースである2.0では、正式な非推奨化なしに、いくつかの大きなAPI変更が検討されています。
上記の変更の一環としてこの変更を行うことをお勧めします。その理由は、
- バグを防ぐのに役立ち、バグを導入しないためです。
- 現在の動作によって発生する可能性のあるバグの深刻さを考えると、pandas 3.0.0まで2年間待つと、大きな損害を招く可能性があります。
これはdateutil.parser
を削除することを意味するものではありません。これはguess_datetime_format
内で引き続き使用されます。しかし、この提案では、後続の行は推測された形式でパースされ、dateutil.parser
を繰り返し呼び出して、形式が黙って切り替わるリスクを回避します。
最後に、関数from pandas._libs.tslibs.parsing import guess_datetime_format
は、pandas.tools
の下で公開されます。
範囲外
形式を推測するために要素のランダムサンプルを使用することで、guess_datetime_format
をよりスマートにすることができます。
PDEP履歴
- 2022年9月18日: 初期ドラフト
- 2023年1月25日:
format='ISO8601'
とformat='mixed'
オプションについて言及するように修正