Pandas:在多索引数据帧中重新索引和插值
Posted
技术标签:
【中文标题】Pandas:在多索引数据帧中重新索引和插值【英文标题】:Pandas: re-index and interpolate in multi-index dataframe 【发布时间】:2019-05-16 04:57:12 【问题描述】:我无法理解 pandas reindex
。我有一系列测量值,被整合到一个多索引 df
中,我想重新索引并插入这些测量值以将它们与其他一些数据对齐。
我的实际数据有大约 7 个指数级别和几个不同的测量值。我希望这个玩具数据问题的解决方案适用于我的真实数据。这是“小数据”;每个单独的测量值是几个 KB。
这是一对玩具问题,一个显示预期的行为,一个似乎没有做任何事情。
单级索引,按预期工作:
"""
step,value
1,1
3,2
5,1
"""
df_i = pd.read_clipboard(sep=",").set_index("step")
print(df_i)
new_index = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9])
df_i = df_i.reindex(new_index).interpolate()
print(df_i)
输出,原始 df 和重新索引和插值的:
value
step
1 1
3 2
5 1
value
step
1 1.0
2 1.5
3 2.0
4 1.5
5 1.0
6 1.0
7 1.0
8 1.0
9 1.0
效果很好。
多索引,目前不工作:
"""
sample,meas_id,step,value
1,1,1,1
1,1,3,2
1,1,5,1
1,2,3,2
1,2,5,2
1,2,7,1
1,2,9,0
"""
df_mi = pd.read_clipboard(sep=",").set_index(["sample", "meas_id", "step"])
print(df_mi)
df_mi = df_mi.reindex(new_index, level="step").interpolate()
print(df_mi)
输出,重新索引后(因此插值后)不变:
value
sample meas_id step
1 1 1 1
3 2
5 1
2 3 2
5 2
7 1
9 0
value
sample meas_id step
1 1 1 1
3 2
5 1
2 3 2
5 2
7 1
9 0
我如何实际上重新索引多索引 df 中的列?
这是我想要的输出,假设是线性插值:
value
sample meas_id step
1 1 1 1
2 1.5
3 2
5 1
6 1
7 1
8 1
9 1
2 1 NaN (or 2)
2 NaN (or 2)
3 2
4 2
5 2
6 1.5
7 1
8 0.5
9 0
我花了一些真诚的时间查看 SO,如果答案在那里,我错过了:
Fill multi-index Pandas DataFrame with interpolation
Resampling Within a Pandas MultiIndex
pandas multiindex dataframe, ND interpolation for missing values
Fill multi-index Pandas DataFrame with interpolation
https://pandas.pydata.org/pandas-docs/stable/basics.html#basics-reindexing
可能相关的 GitHub 问题:
https://github.com/numpy/numpy/issues/11975
https://github.com/pandas-dev/pandas/issues/23104
https://github.com/pandas-dev/pandas/issues/17132
【问题讨论】:
你的预期输出是多少 我会将它添加到我的问题中,但我希望重新索引和插值类似于单索引数据帧的行为。 【参考方案1】:IIUC 使用MultiIndex.from_product
创建索引,然后直接使用reindex
idx=pd.MultiIndex.from_product([df_mi.index.levels[0],df_mi.index.levels[1],new_index])
df_mi.reindex(idx).interpolate()
Out[161]:
value
1 1 1 1.000000
2 1.500000
3 2.000000
4 1.500000
5 1.000000
6 1.142857
7 1.285714
8 1.428571
9 1.571429
2 1 1.714286 # here is bad , it take previous value into consideration
2 1.857143
3 2.000000
4 2.000000
5 2.000000
6 1.500000
7 1.000000
8 0.500000
9 0.000000
我的想法
def idx(x):
idx = pd.MultiIndex.from_product([x.index.get_level_values(0).unique(), x.index.get_level_values(1).unique(), new_index])
return idx
pd.concat([y.reindex(idx(y)).interpolate() for _,y in df_mi.groupby(level=[0,1])])
value
1 1 1 1.0
2 1.5
3 2.0
4 1.5
5 1.0
6 1.0
7 1.0
8 1.0
9 1.0
2 1 NaN
2 NaN
3 2.0
4 2.0
5 2.0
6 1.5
7 1.0
8 0.5
9 0.0
【讨论】:
谢谢 - 你说得对,插值很糟糕。对于我的数据,如果其他索引值发生变化(这里,meas_id
从 1 更改为 2),我不能有那种“串扰”。
@Evan 检查我的方法。 :-) 希望它能解决问题,并且 interpolate 也不会处理填充问题,这就是为什么你在第二个中使用 NaN 与单个索引类似,重新索引输出
它确实解决了玩具问题!我将尝试将其应用于我的实际问题并跟进那里的任何问题。谢谢!
当然。似乎reindex
仍然无法正常工作,并且您的解决方法(非常好)不应该是必要的。我也担心它会如何扩展,但是笨拙的适应对于熊猫来说是很正常的......以上是关于Pandas:在多索引数据帧中重新索引和插值的主要内容,如果未能解决你的问题,请参考以下文章
Pandas 将时间序列数据重新采样为 15 分钟和 45 分钟 - 使用多索引或列