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

时间:2018-01-02 22:55:11

标签: pandas numpy interpolation

我有一个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)

如何创建索引为newindex的数据框,并从旧的x值中插入新的x值?

第一个新x值应与第一个旧x值相同。同上最后x值。也就是说,开头不应该有NaN,最后一个旧x的副本会重复。

其他应该插值以适应新的等间距索引。

我尝试了df.interpolate(),但无法确定如何针对newindex进行插值。

提前感谢您的帮助。

3 个答案:

答案 0 :(得分:2)

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

例如,您声明的newindex仅与index中的第一个和最后一个数字重叠,因此线性插值(正确)会在开始(2)和结束(27)之间插入一条直线。你的index

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

答案 1 :(得分:1)

这很好用:

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

答案 2 :(得分:0)

我采用了以下解决方案:

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