今回はpandasを使って、一部の日付がシリアル値として記録されたデータを、Datetime型に統一する方法を紹介する。

サンプルデータフレームの用意

まずは例題として使用するサンプルデータフレームを用意する。

import pandas as pd

df = pd.DataFrame([['0001', '2019/11/01'],
                  ['0002', '2019/11/02'],
                  ['0003', '44395'],
                  ['0004', '44441']],
                 columns=['売上ID', '売上日'])

#    売上ID         売上日
# 0  0001  2019/11/01
# 1  0002  2019/11/02
# 2  0003       44395
# 3  0004       44441

データ形式の統一されていないExcelファイルなどからデータをpandasデータフレームに変換すると、しばしば上記のように日付がシリアル値として読み込まれることがある。

to_timedelta関数

今回はto_timedelta関数を使って変換を行う。

timedelta形式の詳細については以下の記事で軽く触れている。

実際にシリアル値をtimedelta形式に変換してみた。
引数のunitは単位を表し、今回は日付単位の「D」を指定した。

x = pd.to_timedelta(df.loc[2, "売上日"], unit="D")
print(x)
# 43796 days 00:00:00

to_timedelta関数を応用して一括変換を行う

まず、シリアル値が登録されている行を特定するため、変数flgに該当行を記録する。
Trueとなっている行がシリアル値となっている行だ。

flg = df["売上日"].astype("str").str.isdigit()

# 0    False
# 1    False
# 2     True
# 3     True
# Name: 売上日, dtype: bool

次に、to_timedelta関数を使ってシリアル値を日付型に変換する。

from_serial = pd.to_timedelta(df.loc[flg, "売上日"].astype("float"), unit="D") + pd.to_datetime("1900/1/1")

# 2   2019-11-29
# 3   2019-12-02
# Name: 売上日, dtype: datetime64[ns]

そして最後に変換したデータを元データに結合すれば処理は完了だ。

# 書式の統一
from_string = pd.to_datetime(df.loc[~flg, "売上日"])

# 結合
df["売上日"] = pd.concat([from_serial, from_string])

#    売上ID        売上日
# 0  0001 2019-11-01
# 1  0002 2019-11-02
# 2  0003 2019-11-29
# 3  0004 2019-12-02

これで、登録日がきれいに補正されていることが確認できた。