如何匹配DataFrame列值与查找表,用偏移累积和填充数据?
Pandas 实现匹配行后累积和填充需求
需求说明
现有两个Pandas DataFrame:
- Data_One_df:包含日期、时间、剩余条数字段,以及多个以时间命名的空列
- Data_Two_df:包含时间和对应的Fcst数值字段
需要实现:将Data_One_df的Time列与Data_Two_df的Time列匹配,对Data_Two_df中匹配行下一行开始的Fcst列计算累积和,将该值填充到Data_One_df中匹配列的右侧一列对应的行,且后续所有时间列的该行都保持这个值。
举个例子:Data_One_df中6:30行匹配Data_Two_df的6:30行后,取Data_Two_df中6:35到7:00的Fcst累积和(2+1+1+2+1+1=8),填充到Data_One_df的6:35列的6:30行,同时6:40、6:45等后续列的6:30行都保留8。
现有数据代码
import pandas as pd # 创建Data_One_df data_one = { "Date": ["12/1/2022"] * 7, "Time": ["6:30", "6:35", "6:40", "6:45", "6:50", "6:55", "7:00"], "Bars_left": [6, 5, 4, 3, 2, 1, 0], "6:30": [""] * 7, "6:35": [""] * 7, "6:40": [""] * 7, "6:45": [""] * 7, "6:50": [""] * 7, "6:55": [""] * 7, "7:00": [""] * 7, } Data_One_df = pd.DataFrame(data_one) # 创建Data_Two_df data_two = { "Time": ["6:30", "6:35", "6:40", "6:45", "6:50", "6:55", "7:00"], "Fcst": [1, 2, 1, 1, 2, 1, 1], } Data_Two_df = pd.DataFrame(data_two)
预期结果
import pandas as pd data_three = { "Date": ["12/1/2022"] * 7, "Time": ["6:30", "6:35", "6:40", "6:45", "6:50", "6:55", "7:00"], "Bars_left": [6, 5, 4, 3, 2, 1, 0], "6:30": [pd.NA] * 7, "6:35": [8, pd.NA, pd.NA, pd.NA, pd.NA, pd.NA, pd.NA], "6:40": [8, 6, pd.NA, pd.NA, pd.NA, pd.NA, pd.NA], "6:45": [8, 6, 5, pd.NA, pd.NA, pd.NA, pd.NA], "6:50": [8, 6, 5, 4, pd.NA, pd.NA, pd.NA], "6:55": [8, 6, 5, 4, 2, pd.NA, pd.NA], "7:00": [8, 6, 5, 4, 2, 1, pd.NA], } Desired_df = pd.DataFrame(data_three)
尝试的错误代码
# 获取时间列列表 time_cols = Data_One_df.columns[3:] # 遍历时间列并基于Data_Two_df更新值 for i, col in enumerate(time_cols): # 从Data_Two_df获取对应预测值 fcst = Data_Two_df["Fcst"][i] # 基于预测值更新Data_One_df的值 Data_One_df[col] = [np.nan] * fcst + list(Data_One_df[col][fcst:])
正确实现方案
思路解析
- 计算Data_Two_df中Fcst列的反向累积和:从最后一行往前累加,得到每个行对应的「下一行到末尾」的Fcst总和,正好匹配需求中的累积和要求
- 构建填充矩阵:仅在列索引大于行索引的位置填充对应累积和值,其余位置设为NaN,对应到Data_One_df中就是当前行的右侧列
- 将矩阵赋值到Data_One_df的时间列,完成填充
完整代码
import pandas as pd import numpy as np # 原数据创建(可保留用户的原有数据定义) data_one = { "Date": ["12/1/2022"] * 7, "Time": ["6:30", "6:35", "6:40", "6:45", "6:50", "6:55", "7:00"], "Bars_left": [6, 5, 4, 3, 2, 1, 0], "6:30": [""] * 7, "6:35": [""] * 7, "6:40": [""] * 7, "6:45": [""] * 7, "6:50": [""] * 7, "6:55": [""] * 7, "7:00": [""] * 7, } Data_One_df = pd.DataFrame(data_one) data_two = { "Time": ["6:30", "6:35", "6:40", "6:45", "6:50", "6:55", "7:00"], "Fcst": [1, 2, 1, 1, 2, 1, 1], } Data_Two_df = pd.DataFrame(data_two) # 步骤1:计算反向累积和,shift(1)获取下一行开始的总和,最后一行无后续行填充0 rev_cumsum = Data_Two_df["Fcst"][::-1].cumsum()[::-1].shift(1).fillna(0) # 步骤2:获取时间列列表 time_cols = Data_One_df.columns[3:] n_rows, n_cols = len(Data_One_df), len(time_cols) # 构建填充矩阵:列索引>行索引时填充累积和,否则为NaN fill_matrix = np.full((n_rows, n_cols), np.nan) for row_idx in range(n_rows): for col_idx in range(n_cols): if col_idx > row_idx: fill_matrix[row_idx, col_idx] = rev_cumsum.iloc[row_idx] # 步骤3:赋值到Data_One_df Data_One_df[time_cols] = fill_matrix # 查看结果(可选) print(Data_One_df)
代码说明
rev_cumsum:通过反向累加再反转,得到每个行对应的后续所有Fcst的总和,比如行0(6:30)对应的总和为8,行1(6:35)对应的总和为6,完全匹配预期- 填充矩阵逻辑:确保只有当前行的右侧列才会填充值,符合需求中"匹配列右侧一列起填充"的要求
- 最终赋值后,每个行的右侧所有列都会保持同一个累积和值,与预期结果完全一致
内容的提问来源于stack exchange,提问作者rer50
相关产品推荐
相关产品推荐

