pyhton3のdt.round
時間を指定した区切りに丸めることができる。
rng = pd.date_range('1/1/2018 11:59:00', periods=3, freq='min')
print(rng)
print(rng.round('H')) # 'H':時間で丸める
"""出力
DatetimeIndex(['2018-01-01 11:59:00', '2018-01-01 12:00:00',
'2018-01-01 12:01:00'],
dtype='datetime64[ns]', freq='T')
DatetimeIndex(['2018-01-01 12:00:00', '2018-01-01 12:00:00',
'2018-01-01 12:00:00'],
dtype='datetime64[ns]', freq=None)
"""
ドキュメント
やること
このdt.round(時間の丸め)を使う際に入力時間を細かくして確認したときに
想定と違う動作をしたので、それについてアウトプットする。
実行環境
windows 11
python 3.10.5
pandas 1.5.1
使い方
import pandas as pd
df_date = pd.DataFrame({'初期': ['2022-11-26 12:07:30', '2022-11-26 12:07:31']})
df_date['初期'] = pd.to_datetime(df_date['初期']) # 文字列をdatetimeに変換する
df_date['round'] = df_date['初期'].dt.round("15T")
print(df_date)
""" 出力
初期 round
0 2022-11-26 12:07:30 2022-11-26 12:00:00
1 2022-11-26 12:07:31 2022-11-26 12:15:00
"""
round("15T")で15分丸めを指定した場合
半分である7分30秒を基準時間として出力が
「切り上げ、切り捨て」と変化する
入力時間を細かく変えて確認
15分丸め
df_time = pd.DataFrame(pd.date_range(start='2022-01-01 12:07:00', periods=60, freq="1S", name="初期"))
# 半分を基準に切り上げ、切り捨てする
df_time['round'] = df_time['初期'].dt.round("15T")
print(df_time)
df_time.to_csv("time_round.csv")
丸め時間を「15分、30分、45分、00分」と変化するように
入力データ(1秒ごとの時間データ)を生成して確認すると
丸め時間によって切り替わる基準時間が
30秒と31秒に分かれる。
10分丸め
roundは「偶数に丸めようとする」
というのがあるので、丸め時間を10分(偶数)にすると
切り替わる基準時間が同じになると想定し試すと
基準時間が1秒と0秒と別れ、想定通りにならなかったが
15分丸めと同じように「切り上げ、切り捨て」を繰り替えしているのがわかる
1分丸め
見えてきた法則
x(=1)分区切りの時
- 丸め時間の半分が基準時間となるx分/2(=30秒)の
- 「x(=1)分、3x(=3)分、5x(=5)分・・・」の時の基準時間は切り捨て(奇数のような動作?)
- 「0分、2x(=2)分、4x(=4)分・・・」の時の基準時間は切り上げ(偶数のような動作?)
3のように「丸め時間の2倍」を「偶数」のように扱い、
基準時間の時に「偶数」側に近づくように丸める
丸め基準時間を固定するには
「時間で判定して切り上げ、切り捨て」というように
処理を自分で書くしかなさそう
丸め基準時間固定の1分区切り
def df_time_round(df_datetimes):
# 引数のDataFrameをコピー
return_df_datetimes = df_datetimes.copy()
for index, time in enumerate(df_datetimes):
# 30秒以下の場合
if time.second <= 30:
# 1分区切りの切り捨て
return_df_datetimes[index] = time.floor(freq='1T')
# 31秒以上の場合
else:
# 1分区切りの切り上げ
return_df_datetimes[index] = time.ceil(freq='1T')
return return_df_datetimes
minute_num = 1
df_time = pd.DataFrame(pd.date_range(start='2022-01-01 12:' + str(minute_num) + ':00', periods=60, freq="1S", name="initial"))
# 関数で処理した結果を返し、csvに出力
df_time["new_round"] = df_time_round(df_time['initial'])
df_time.to_csv("time_round1_" + str(minute_num) + ".csv")
まとめ
細かい話で確認や推測を立てるのが大変だが
分析すると法則が見えてくるなと思いました。