У меня есть CSV-файл, который выглядит следующим образом, когда я загружаю его:
# generate example data
users = ['A', 'B', 'C', 'D']
#dates = pd.date_range("2020-02-01 00:00:00", "2020-04-04 20:00:00", freq="H")
dates = pd.date_range("2020-02-01 00:00:00", "2020-02-04 20:00:00", freq="H")
idx = pd.MultiIndex.from_product([users, dates])
idx.names = ["user", "datehour"]
y = pd.Series(np.random.choice(a=[0, 1], size=len(idx)), index=idx).rename('y')
# write to csv and reload (turns out this matters)
y.to_csv('reprod_example.csv')
y = pd.read_csv('reprod_example.csv', parse_dates=['datehour'])
y = y.set_index(['user', 'datehour']).y
>>> y.head()
user datehour
A 2020-02-01 00:00:00 0
2020-02-01 01:00:00 0
2020-02-01 02:00:00 1
2020-02-01 03:00:00 0
2020-02-01 04:00:00 0
Name: y, dtype: int64
У меня есть следующая функция для создания отстающих функций индекса уровня:
def shift_index(a, dt_idx_name, lag_freq, lag):
# get datetime index of relevant level
ac = a.copy()
dti = ac.index.get_level_values(dt_idx_name)
# shift it
dti_shifted = dti.shift(lag, freq=lag_freq)
# put it back where you found it
ac.index.set_levels(dti_shifted, level=dt_idx_name, inplace=True)
return a
Но когда я запускаю: y_lag = shift_index(y, 'datehour', 'H', 1)
, я получаю следующую ошибку:
ValueError: Level values must be unique...
(я могу на самом деле устранить эту ошибку, добавив verify_integrity=False
в .index.set_levels...
в функции, но это (как и ожидалось) вызывает проблемы в будущем)
Вот странная часть. Если вы запустили приведенный выше пример, но без сохранения / перезагрузки из CSV, это работает. Кажется, причина в том, что y.index.get_level_value('datehour')
показывает атрибут freq='H'
сразу после его создания, но freq=None
после его перезагрузки из CSV.
Это имеет смысл, очевидно, CSV не сохраняет эти метаданные. Но я обнаружил, что на удивление сложно установить атрибут freq для серии MultiIndexed. Например, это ничего не сделало. df.index.freq = pd.tseries.frequencies.to_offset("H")
. И этот ответ также не работал для моего MultiIndex.
Так что я думаю, что мог бы решить эту проблему, если бы мне удалось установить атрибут freq
компонента DateTime моего MultiIndex. Но моей конечной целью является создание версии моих y
данных со смещенным компонентом DateTime MultiIndex, как, например, с моей функцией shift_index
выше. Поскольку я получаю свои данные через CSV, «просто не сохранять в CSV и перезагрузить» не вариант.