为pandas DataFrame设置新索引(插值?)

8

我有一个DataFrame,其中索引不是时间。 我需要将所有旧索引的值重新调整到一个新索引上,这个新索引具有不同的极限和等距间隔。

列中的第一个和最后一个值应该保持不变(虽然它们将被赋予新的、伸展的索引值)。

示例代码如下:

import numpy as np
import pandas as pd
%matplotlib inline

index = np.asarray((2, 2.5, 3, 6, 7, 12, 15, 18, 20, 27))
x = np.sin(index / 10)

df = pd.DataFrame(x, index=index)
df.plot();

newindex = np.linspace(0, 29, 100)

如何创建一个DataFrame,其中索引为newindex,新的x值从旧的x值插值得到?
第一个新的x值应与第一个旧的x值相同。最后一个x值也是如此。也就是说,在开头不应该有NaN,在结尾重复最后一个旧x。
其他值应该插值以适应新的等间隔索引。
我尝试过df.interpolate(),但无法解决如何针对newindex进行插值的问题。
感谢您提前的帮助。

你看过这个问题吗?https://dev59.com/zF0a5IYBdhLWcg3wsKUK - Evan
是的:大多数现有的答案(和文档)都有日期或时间索引,但我的没有。如果索引是日期或时间,重新索引似乎要容易得多。 - blokeley
3个回答

7

这个运行良好:

import numpy as np
import pandas as pd

def interp(df, new_index):
    """Return a new DataFrame with all columns values interpolated
    to the new_index values."""
    df_out = pd.DataFrame(index=new_index)
    df_out.index.name = df.index.name

    for colname, col in df.iteritems():
        df_out[colname] = np.interp(new_index, df.index, col)

    return df_out

非数值类型的插值可能需要特别注意。 - FObersteiner

6
我采用了以下解决方案:
import numpy as np
import pandas as pd
import matplotlib.pylab as plt

def reindex_and_interpolate(df, new_index):
    return df.reindex(df.index | new_index).interpolate(method='index', limit_direction='both').loc[new_index]

index = np.asarray((2, 2.5, 3, 6, 7, 12, 15, 18, 20, 27))
x = np.sin(index / 10)

df = pd.DataFrame(x, index=index)

newindex = pd.Float64Index(np.linspace(min(index)-5, max(index)+5, 50))

df_reindexed = reindex_and_interpolate(df, newindex)

plt.figure()
plt.scatter(df.index, df.values, color='red', alpha=0.5)
plt.scatter(df_reindexed.index, df_reindexed.values,  color='green', alpha=0.5)
plt.show()

enter image description here


NameError: name 'merged_index' is not defined - blokeley
@blokeley 修复了它。 - João Abrantes
2
df.index | new_index 可能会导致 FutureWarning: Index.__or__ operating as a set operation is deprecated #code。在较新版本的Pandas中,最好使用 df.index.union(new_index) - J. Choi

3

我想知道您是否遇到了pandas的限制;看起来您在将df与任意一组数字(您的newindex)对齐时选择有限。

例如,您所述的newindex仅与index中的第一个和最后一个数字重叠,因此线性插值(正确地)在index的起始点(2)和终止点(27)之间插值出一条直线。

import numpy as np
import pandas as pd
%matplotlib inline

index = np.asarray((2, 2.5, 3, 6, 7, 12, 15, 18, 20, 27))
x = np.sin(index / 10)

df = pd.DataFrame(x, index=index)

newindex = np.linspace(min(index), max(index), 100)

df_reindexed = df.reindex(index = newindex)
df_reindexed.interpolate(method = 'linear', inplace = True)

df.plot()
df_reindexed.plot()

image1

如果您将newindex更改为与原始数据集提供更多的重叠点,插值将以更符合预期的方式工作:

newindex = np.linspace(min(index), max(index), 26)

df_reindexed = df.reindex(index = newindex)
df_reindexed.interpolate(method = 'linear', inplace = True)

df.plot()
df_reindexed.plot()

image2

还有其他方法不需要手动对齐索引,但得到的曲线(虽然在技术上是正确的)可能不是我们想要的:

newindex = np.linspace(min(index), max(index), 1000)

df_reindexed = df.reindex(index = newindex, method = 'ffill')

df.plot()
df_reindexed.plot()

image3

我查看了pandas文档,但我无法找到一个简单的解决方案。

https://pandas.pydata.org/pandas-docs/stable/basics.html#basics-reindexing


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接