如何在Pandas中仅对非空区间插值并合并DataFrame?
问题描述
我有两个示例DataFrame:
import pandas as pd import numpy as np 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]})
df1输出:
Depth GR 0 1100 40.0 1 1110 50.0 2 1120 60.0 3 1130 NaN 4 1140 70.0
df2输出:
Depth VSH 0 1100 60.0 1 1112 70.0 2 1118 NaN 3 1128 40.0 4 1138 70.0
核心需求
- df1中GR在Depth 1120-1140区间为null,df2中VSH在Depth 1112-1128区间为null
- 基于Depth做外连接后,仅在原数据有有效值的区间内插值:
- GR在1120-1140区间保持null(原数据该区间无有效GR值)
- VSH在1112-1128区间保持null(原数据该区间无有效VSH值)
期望插值后输出:
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在对应Depth无匹配值处的插值为近似值
解决方案
通过外连接+标记有效区间+分段插值的步骤实现需求,具体代码如下:
import pandas as pd import numpy as np # 1. 定义原始数据 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]}) # 2. 全外连接并按Depth排序 merged = pd.merge(df1, df2, on='Depth', how='outer').sort_values('Depth').reset_index(drop=True) # 3. 处理GR的分段插值:仅在原始有效区间内插值 # 获取GR原始非空的深度点,生成有效插值区间 gr_valid_depths = df1[df1['GR'].notna()]['Depth'].sort_values() gr_intervals = list(zip(gr_valid_depths[:-1], gr_valid_depths[1:])) gr_result = merged['GR'].copy() for start, end in gr_intervals: mask = (merged['Depth'] >= start) & (merged['Depth'] <= end) gr_result[mask] = gr_result[mask].interpolate(method='linear') # 4. 处理VSH的分段插值:仅在原始有效区间内插值 vsh_valid_depths = df2[df2['VSH'].notna()]['Depth'].sort_values() vsh_intervals = list(zip(vsh_valid_depths[:-1], vsh_valid_depths[1:])) vsh_result = merged['VSH'].copy() for start, end in vsh_intervals: mask = (merged['Depth'] >= start) & (merged['Depth'] <= end) vsh_result[mask] = vsh_result[mask].interpolate(method='linear') # 5. 替换回合并表并保留一位小数 merged['GR'] = gr_result.round(1) merged['VSH'] = vsh_result.round(1) print(merged)
运行后输出与期望结果一致:
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
代码说明
- 先通过
pd.merge做全外连接并排序,确保深度按顺序排列 - 提取每个列原始非空的深度点,生成仅允许插值的区间(比如GR的有效区间为1100-1120,1140为单个点无需插值)
- 对每个区间内的NaN执行线性插值,区间外的NaN保持不变
- 最后保留一位小数,匹配示例输出格式
内容的提问来源于stack exchange,提问作者Mahammad Ojagzada
相关产品推荐
相关产品推荐

