python - 在 Pandas MultiIndex 中移动 DateTime 索引
问题描述
我有一个 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 ac
但是当我运行: 时
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 显然不会保存该元数据。但是我发现为 MultiIndexed 系列设置 freq 属性非常困难。例如,这什么也没做。
df.index.freq = pd.tseries.frequencies.to_offset("H")
. 这个答案也不适用于我的 MultiIndex 。
因此,如果我能够设置freq
MultiIndex 的 DateTime 组件的属性,我想我可以解决这个问题。但我的最终目标是y
使用移位的 DateTime MultiIndex 组件创建我的数据版本,例如shift_index
上面的函数。由于我通过 csv 接收数据,因此“只是不保存到 csv 并重新加载”不是一个选项。
解决方案
经过一番烦躁之后,我能够使用asfreq('H')
分组数据设置每小时频率,这样每个组都有唯一的datehour
索引值。
y = pd.read_csv('reprod_example.csv', parse_dates=['datehour'])
y = y.groupby('user').apply(lambda df: df.set_index('datehour').asfreq('H')).y
查看索引值显示正确的频率。
y.index[0]
# ('A', Timestamp('2020-02-01 00:00:00', freq='H'))
所有这一切都是将索引设置为两部分。user
优先,以便嵌套索引在其中datehour
可以是唯一的。一旦datehour
索引是唯一的,那么asfreq
就可以毫无困难地使用。
如果您尝试asfreq
使用非唯一索引,它将无法正常工作。
y_load.set_index('datehour').asfreq('H')
# ---------------------------------------------------------------------------
# ValueError Traceback (most recent call last)
# <ipython-input-433-3ba51b619417> in <module>
# ----> 1 y_load.set_index('datehour').asfreq('H')
# ...
# ValueError: cannot reindex from a duplicate axis
推荐阅读
- scala - 构建 Scala 库并在数据块中使用它们
- node.js - 在推送器中调用触发方法时引发错误,“预期字符串”
- firebase - Flutter Firebase document.id 更新问题
- python - 检查数组中的2个或多个项目是否相同并根据排序号删除其中一项 - Python
- python - 如何在 python 中计算股票/加密货币的收盘价和高低差?
- rxjs - RxJs channing、设置和读取外部值
- c# - 如何使用 c#/cmd 向 msi 文件的属性表添加新行
- html - 使用多个模式关闭 Blazor 模式
- java - 使用 Java 序列化从文件中读取对象时出现问题
- numpy - 在行轴中查找矩阵的最大值并将其他值替换为零