如何基于索引匹配合并Pandas DataFrame并保留指定行?
解决Pandas DataFrame按指定规则合并的问题
需求说明
现有两个已排序、无重复、无NaN的Pandas DataFrame:
x_axis:包含连续日期序列df:包含snap_date(要么是x_axis中的日期,要么是0)和对应数据some_data
需要将两者合并为desired_df,规则如下:
- 从
x_axis.date与df.snap_date首次匹配的位置开始,将df的行依次对应到x_axis的行 - 保留
df中snap_date=0的行,不能仅通过日期关联匹配
示例数据
先还原用户提供的示例数据:
import pandas as pd # 构建x_axis x_axis = pd.DataFrame({ 'index': [1,2,3,4,5,6,7,8,9], 'date': ['01-01-2023', '02-01-2023', '03-01-2023', '04-01-2023', '05-01-2023', '06-01-2023', '07-01-2023', '08-01-2023', '09-01-2023'] }).set_index('index') # 构建df df = pd.DataFrame({ 'index': [1,2,3,4,5,6], 'snap_date': ['03-01-2023', '04-01-2023', '05-01-2023', '06-01-2023', 0, 0], 'some_data': [12,85,46,74285,427,452] }).set_index('index')
解决方案代码
# 1. 找到df中第一个非0的snap_date值 first_match_date = df[df['snap_date'] != 0]['snap_date'].iloc[0] # 2. 找到x_axis中首次匹配该日期的行索引 start_pos = x_axis[x_axis['date'] == first_match_date].index[0] # 3. 计算映射的结束位置:从起点开始覆盖df的所有行 end_pos = start_pos + len(df) - 1 # 4. 给x_axis添加df索引映射列 x_axis['df_index'] = None x_axis.loc[start_pos:end_pos, 'df_index'] = df.index.values # 5. 左合并两个DataFrame,保留x_axis所有行 desired_df = x_axis.merge(df, left_on='df_index', right_index=True, how='left') # 6. 调整列名和顺序,匹配期望输出 desired_df = desired_df.reset_index() desired_df = desired_df[['index', 'date', 'df_index', 'snap_date', 'some_data']].rename(columns={'df_index': 'index_y'}) # 查看结果 print(desired_df)
代码解释
- 定位首次匹配点:提取
df中第一个有效的snap_date(非0值),再在x_axis中找到对应行,作为后续数据映射的起点。 - 构建索引映射:从起点开始,将
df的索引依次赋值给x_axis的连续行,确保df的每一行(包括snap_date=0的行)都能精准对应到x_axis的行。 - 合并DataFrame:通过索引映射做左合并,保留
x_axis的所有行,无匹配的行自动填充空值,完全符合需求。
输出结果
运行代码后得到的desired_df与期望一致:
| index | date | index_y | snap_date | some_data |
|---|---|---|---|---|
| 1 | 01-01-2023 | NaN | NaN | NaN |
| 2 | 02-01-2023 | NaN | NaN | NaN |
| 3 | 03-01-2023 | 1 | 03-01-2023 | 12 |
| 4 | 04-01-2023 | 2 | 04-01-2023 | 85 |
| 5 | 05-01-2023 | 3 | 05-01-2023 | 46 |
| 6 | 06-01-2023 | 4 | 06-01-2023 | 74285 |
| 7 | 07-01-2023 | 5 | 0 | 427 |
| 8 | 08-01-2023 | 6 | 0 | 452 |
| 9 | 09-01-2023 | NaN | NaN | NaN |
内容的提问来源于stack exchange,提问作者Paul1911
相关产品推荐
相关产品推荐

