合并后,如何只插值非空间隔?

After merging, how to interpolate only non-null intervals?

提问人:Mahammad Ojagzada 提问时间:11/9/2023 最后编辑:Mahammad Ojagzada 更新时间:11/9/2023 访问量:75

问:

我有两个示例数据帧:

df1 = pd.DataFrame({'Depth':[1100, 1110, 1120, 1130, 1140], 'GR':[40, 50, 60, np.nan, 70]})
df2 = pd.DataFrame({'Depth':[1100, 1112, 1118, 1128, 1138], 'VSH':[60, 70, np.nan, 40, 70]})
   Depth    GR
0   1100  40.0
1   1110  50.0
2   1120  60.0
3   1130   NaN
4   1140  70.0
   Depth   VSH
0   1100  60.0
1   1112  70.0
2   1118   NaN
3   1128  40.0
4   1138  70.0

第一个数据显示,从深度 11201140 的“GR”值为空。同样,在第二个数据帧中,从 11121128 的深度“VSH”为 null。我想通过“深度”上的外部连接来连接这些数据集,并通过插值填充空值,其中实际已知的是“GR”。我的意思是,在最终连接的数据集中,不应插值“GR”值(保持为空),其中“GR”的深度介于 1120 和 1140 之间,因为在此时间间隔内,“GR”与第一个数据集一样未知。同样,深度介于 1112 和 1128 之间的“VSH”值应为 null(不插值)。按特定间隔插值后的输出应为:

merged_df = pd.DataFrame({'Depth':[1100, 1110, 1112, 1118, 1120, 1128, 1130, 1138, 1140], 'GR':[40, 50, 53.3, 56.6, 60, np.nan, np.nan, np.nan, 70], 'VSH':[60, 65, 70, np.nan, np.nan, 40, 55, 70, np.nan]})
   Depth    GR   VSH
0   1100  40.0  60.0
1   1110  50.0  65.0
2   1112  53.3  70.0
3   1118  56.6   NaN
4   1120  60.0   NaN
5   1128   NaN  40.0
6   1130   NaN  55.0
7   1138   NaN  70.0
8   1140  70.0  NaN

注意:我只是对 GR 和 VSH 的插值数字进行了近似的插值,它们分别在 df2 和 df1 中没有相应的深度。

你怎么能在熊猫身上做到这一点?

熊猫 数据帧 插值 熊猫合并

评论

0赞 Corralien 11/9/2023
我不明白 VSH 从 5 到 8 的输出?为什么是 40、50、60、70?深度为 1138 的 VSH 的 80 在哪里?
0赞 wjandrea 11/9/2023
包括您目前所拥有的内容会有所帮助。看起来像,是吗?但是 1138 的 VSH 是 80,而不是 60,因此您可能需要检查详细信息。df1.merge(df2, on='Depth', how='outer', sort=True)
0赞 Corralien 11/9/2023
深度 1140 不可能有 85 的 VSH。因为现在它是一种外推,而不是插值。
0赞 Mahammad Ojagzada 11/9/2023
@wjandrea 是的。我更正了数据,对不起
0赞 Mahammad Ojagzada 11/9/2023
@Corralien啊,我的坏,是的,你是对的

答:

3赞 mozway 11/9/2023 #1

假设您没有无限值,一种选择可能是使用 Inf 作为哨兵来标记这些值不进行插值:

out = (df1.fillna(np.inf)
          .merge(df2.fillna(np.inf),
                 on='Depth',
                 how='outer',
                 sort=True)
          .interpolate()
          .replace(np.inf, np.nan)
       )

输出:

   Depth         GR   VSH
0   1100  40.000000  60.0
1   1110  50.000000  65.0
2   1112  53.333333  70.0
3   1118  56.666667   NaN
4   1120  60.000000   NaN
5   1128        NaN  40.0
6   1130        NaN  55.0
7   1138        NaN  70.0
8   1140  70.000000  70.0

如果要基于深度进行插值并避免外推:

out = (df1.fillna(np.inf)
          .merge(df2.fillna(np.inf),
                 on='Depth',
                 how='outer',
                 sort=True)
          .set_index('Depth')
          .interpolate('index', limit_area='inside')
          .replace(np.inf, np.nan)
          .reset_index()
       )

输出:

   Depth    GR        VSH
0   1100  40.0  60.000000
1   1110  50.0  68.333333
2   1112  52.0  70.000000
3   1118  58.0        NaN
4   1120  60.0        NaN
5   1128   NaN  40.000000
6   1130   NaN  46.000000
7   1138   NaN  70.000000
8   1140  70.0        NaN

评论

0赞 Mahammad Ojagzada 11/9/2023
谢谢!只想提一下,我应该在函数中添加参数。limit_area = inside'.interpolate()
0赞 mozway 11/9/2023
@Muhammad是的,如果您不想“推断”(而不是填充)外部 NaN ;)
2赞 Corralien 11/9/2023 #2

另一个具有实数深度插值的命题:

import scipy as sp

# Create interpolation function
gr = sp.interpolate.interp1d(df1['Depth'], df1['GR'], kind='linear', bounds_error=False)
vsh = sp.interpolate.interp1d(df2['Depth'], df2['VSH'], kind='linear', bounds_error=False)

# Compute interpolation for other depths
df1a = pd.DataFrame({'Depth': df2['Depth'], 'GR': gr(df2['Depth'])})
df2a = pd.DataFrame({'Depth': df1['Depth'], 'VSH': vsh(df1['Depth'])})

# Final dataframe
out = (pd.merge(pd.concat([df1, df1a]),
                pd.concat([df2, df2a]))
         .drop_duplicates('Depth')
         .sort_values('Depth', ignore_index=True))

输出:

>>> out
   Depth    GR        VSH
0   1100  40.0  60.000000
1   1110  50.0  68.333333
2   1112  52.0  70.000000
3   1118  58.0        NaN
4   1120  60.0        NaN
5   1128   NaN  40.000000
6   1130   NaN  46.000000
7   1138   NaN  70.000000
8   1140  70.0        NaN

对于 GR-1112 和 GR-1118,您期望 53.3 和 56.6,因为 GR-1110 (50) 和 GR-1120 (60) 之间有两个空值,但这没有考虑深度的实际值。对我来说,基于深度进行插值比缺失值的数量更有意义,对吧?

评论

0赞 Mahammad Ojagzada 11/9/2023
谢谢!您的解决方案也是正确的。