插值PANDAS数据框

3

我知道这个主题在stackoverflow上已经被提及了几次,但是我仍然遇到了插值问题。

我有一个复杂的数据框,其中包含一组列,如果简化后可能看起来像这样:

df_new = pd.DataFrame(np.random.randn(5,7), columns=[402.3, 407.2, 412.3, 415.8, 419.9, 423.5, 428.3])
wl     = np.array([400.0, 408.2, 412.5, 417.2, 420.5, 423.3, 425.0])

所以我需要做的是按列进行插值,对于每一行将列的新分配值(wl)进行插值。

如何获得仅包含在wl数组中呈现的值的新数据框?

1个回答

5
使用reindexwl包含为新列(其值将填充为NaN)。 然后使用interpolate(axis=1)在列之间进行插值。 严格来说,插值仅在已知值之间进行。 但是,您可以使用limit_direction='both'在向前和向后方向上填充 NaN边缘值:
>>> df_new.reindex(columns=df_new.columns.union(wl)).interpolate(axis=1, limit_direction='both')
      400.0     402.3     407.2     408.2     412.3     412.5     415.8     417.2     419.9     420.5     423.3     423.5     425.0     428.3
0  0.342346  0.342346  1.502418  1.102496  0.702573  0.379089  0.055606 -0.135563 -0.326732 -0.022298  0.282135  0.586569  0.164917 -0.256734
1 -0.220773 -0.220773 -0.567199 -0.789194 -1.011190 -0.485832  0.039526 -0.426771 -0.893069 -0.191818  0.509432  1.210683  0.414023 -0.382636
2  0.078147  0.078147  0.335040 -0.146892 -0.628824 -0.280976  0.066873 -0.881153 -1.829178 -0.960608 -0.092038  0.776532  0.458758  0.140985
3 -0.792214 -0.792214  0.254805  0.027573 -0.199659 -1.173250 -2.146841 -1.421482 -0.696124 -0.073018  0.550088  1.173194 -0.049967 -1.273128
4 -0.485818 -0.485818  0.019046 -1.421351 -2.861747 -1.020571  0.820605  0.097722 -0.625160 -0.782700 -0.940241 -1.097781 -0.809617 -0.521453

请注意,Pandas数据框架以主要基于列的数据结构存储值。因此,计算通常在列方向上比行方向上更有效率。因此,最好将您的数据框转置:
df = df_new.T

然后按照上面描述的类似方式进行:
df = df.reindex(index=df.index.union(wl))
df = df.interpolate(limit_direction='both')

如果您想外推边缘值,可以使用 scipy.interpolate.interp1d 并使用 fill_value='extrapolate'
import numpy as np
import pandas as pd
import scipy.interpolate as interpolate
np.random.seed(2018)

df_new = pd.DataFrame(np.random.randn(5,7), columns=[402.3, 407.2, 412.3, 415.8, 419.9, 423.5, 428.3])
wl = np.array([400.0, 408.2, 412.5, 417.2, 420.5, 423.3, 425.0, 500])

x = df_new.columns
y = df_new.values
newx = x.union(wl)
result = pd.DataFrame(
    interpolate.interp1d(x, y, fill_value='extrapolate')(newx),
    columns=newx)

产生。
      400.0     402.3     407.2     408.2     412.3     412.5     415.8     417.2     419.9     420.5     423.3     423.5     425.0     428.3      500.0
0 -0.679793 -0.276768  0.581851  0.889017  2.148399  1.952520 -1.279487 -0.671080  0.502277  0.561236  0.836376  0.856029  0.543898 -0.142790 -15.062654
1  0.484717  0.110079 -0.688065 -0.468138  0.433564  0.437944  0.510221  0.279613 -0.165131 -0.362906 -1.285854 -1.351779 -0.758526  0.546631  28.904127
2  1.303039  1.230655  1.076446  0.628001 -1.210625 -1.158971 -0.306677 -0.563028 -1.057419 -0.814173  0.320975  0.402057  0.366778  0.289165  -1.397156
3  2.385057  1.282733 -1.065696 -1.191370 -1.706633 -1.618985 -0.172797 -0.092039  0.063710  0.114863  0.353577  0.370628 -0.246613 -1.604543 -31.108665
4 -3.360837 -2.165729  0.380370  0.251572 -0.276501 -0.293597 -0.575682 -0.235060  0.421854  0.469009  0.689062  0.704780  0.498724  0.045401  -9.804075

如果您想创建一个仅包含wl列的DataFrame,可以使用result[wl]进行子选择,或者只在wl值处进行插值。
result_wl = pd.DataFrame(
    interpolate.interp1d(x, y, fill_value='extrapolate')(wl),
    columns=wl)

1
你的实际DataFrame和这里展示的玩具数据之间必须有一些差异。很抱歉我猜不出这种差异可能是什么。但也许我们应该先确定你实际想要的行为。你只想在边缘上填充NaN值吗?(limit_direction='both'应该是这样做的),还是你想外推值?如果是这样,我认为我需要修改我的帖子,因为df.interpolate不能做到这一点。相反,我认为你可能需要使用scipy.interpolate.interp1d(..., fill_value='extrapolate') - unutbu
如果您能构建一个(希望简单的)可运行示例来演示问题,我或这里的其他人可能可以找出如何修复它。 - unutbu
我不知道问题出在哪里,因为在实施大数据集之前,我使用了完全相同的示例。但是我非常感谢您的帮助,答案非常有用,非常感谢!您是对的,我确实可以使用scipy中的extrapolate来解决这个问题。 - PEBKAC
1
@PEBKAC:要么使用result[wl]子选择wl列,或者如果您知道这些是您想要的唯一列,则可以直接构造此DataFrame,仅在wl值处进行插值。我已编辑上面的帖子以显示我的意思。 - unutbu
df_new.reindex(columns=df_new.columns.union(wl)).interpolate(axis=1, limit_direction='both')[wl] - 我刚刚尝试在您的建议末尾添加[wl],它也可以工作。 - PEBKAC
显示剩余2条评论

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