我有一个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
进行插值。
提前感谢您的帮助。
答案 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()
如果您更改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()
还有其他方法不需要手动对齐索引,但结果曲线(虽然技术上正确)可能不是你想要的:
newindex = np.linspace(min(index), max(index), 1000)
df_reindexed = df.reindex(index = newindex, method = 'ffill')
df.plot()
df_reindexed.plot()
我查看了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()