2025, Nov 03 12:02
Корректное формирование timestamp из смещений в Pandas
Почему метки времени в Pandas кажутся одинаковыми: миллисекунды против микросекунд. Как масштабировать смещения и использовать Timedelta без ошибок в Pandas
Когда вы формируете столбец меток времени из смещения в миллисекундах, сохранённого в CSV, незаметная несогласованность единиц может создать впечатление, что значения не меняются, хотя на самом деле они меняются. Типичная ситуация: смещения заданы в долях миллисекунды, а код интерпретирует их как целые миллисекунды. В результате меняются лишь микросекунды — это легко упустить при беглом просмотре.
Постановка задачи
Набор данных содержит столбец смещений, например: 0, 0.005, 0.01, 0.015, 0.02, которые предполагается накладывать на текущее время для построения временного ряда. Изначальный подход: взять базовую дату-время от now() и прибавить pandas Timedelta в миллисекундах, рассчитанную по этому столбцу.
from datetime import datetime
import pandas as pd
# Пример входных данных
data_map = {
'ms_delta': [0, 0.005, 0.01, 0.015, 0.02],
'col_x': [100, 101, 103, 104, 103],
'col_y': [200, 20.1, 20.1, 24.1, 40.1]
}
frame = pd.DataFrame(data_map)
anchor = datetime.today()
frame['ts_col'] = (
datetime(
anchor.year, anchor.month, anchor.day,
anchor.hour, anchor.minute, anchor.second, anchor.microsecond
)
+ pd.to_timedelta(frame['ms_delta'], unit='ms')
)
Почему метки времени выглядят одинаково
Смещения — не целые миллисекунды; это дробные величины вроде 0.005. Интерпретация 0.005 при unit='ms' означает «пять тысячных миллисекунды», то есть 5 микросекунд. В итоге получается последовательность, отличающаяся только в последних микросекундах. Разница реальна, но невелика и её легко не заметить при просмотре. Иными словами, если 0.005 трактовать как миллисекунды, ваши дельты окажутся в диапазоне микросекунд.
Если цель — применять целые миллисекунды, соответствующие числам 0, 0.005, 0.01, 0.015, 0.02 как 0, 5, 10, 15, 20 миллисекунд, смещения нужно предварительно масштабировать. Кроме того, инициализация базовой даты-времени с микросекундами усложняет чтение различий: микросекунды уже заданы до прибавления дельт.
Правильный подход
Преобразуйте дробные миллисекунды в целые миллисекунды, умножив на 1000, и создайте базовую дату-время без микросекунд. Затем прибавьте Timedelta в миллисекундах. Так сохраняется задуманная семантика: значения вроде 0.005 превращаются в 5 мс вместо 5 мкс.
from datetime import datetime
import pandas as pd
# Пример данных
rows = {
'ms_delta': [0, 0.005, 0.01, 0.015, 0.02],
'col_x': [100, 101, 103, 104, 103],
'col_y': [200, 20.1, 20.1, 24.1, 40.1]
}
dataset = pd.DataFrame(rows)
# Преобразуем доли миллисекунды в целые миллисекунды
dataset['ms_delta'] = dataset['ms_delta'] * 1000
now_ref = datetime.today()
base_dt = datetime(
now_ref.year, now_ref.month, now_ref.day,
now_ref.hour, now_ref.minute, now_ref.second
)
# Прибавляем Timedelta в миллисекундах
dataset['ts_col'] = base_dt + pd.to_timedelta(dataset['ms_delta'], unit='ms')
Почему это важно
Арифметика времени принципиальна к единицам измерения. Столбец, который на вид содержит миллисекунды, но фактически хранит доли миллисекунды, при прямой передаче в Timedelta с unit='ms' даст сдвиги на уровне микросекунд. Такая несогласованность влияет на поведение ряда и на то, как он воспринимается при отладке. Согласование единиц с вашей задумкой помогает избежать тихих ошибок точности и снижает путаницу при проверке результатов.
Выводы
Явно определяйте единицы измерения в столбце со смещениями и согласовывайте их с unit, используемым в Timedelta. Если значения — доли миллисекунды, а требуются целые миллисекунды, сначала приведите их к нужной единице. Формирование базовой метки времени без микросекунд также помогает сразу увидеть прогресс в миллисекундах. С этими правками временной столбец будет отражать дельты как задумано и его проще проверять.