如何在Python Pandas中基于两列值生成DataFrame新行并维护列值
Pandas生成缺失日期行的实现方案
输入数据(survey和event列为object日期类型)
import pandas as pd data = [ (1, 2, 1, 0.33, '2023-10-10', '2023-09-25', 1, 20, 11), (1, 2, 1, 0.33, '2023-10-10', '2023-10-04', 0, 10, 10), (1, 5, 0, 0.58, '2023-05-05', '2023-05-01', 0, 10, None), (2, 8, 1, 0.45, '2023-02-13', '2023-02-10', 0, 25, 10), (2, 8, 1, 0.45, '2023-02-13', '2023-02-02', None, 12, None) ] df = pd.DataFrame(data, columns=['id', 'nps', 'target', 'score', 'survey', 'event', 'col1', 'col2', 'col3'])
需求
- 针对每个
id+survey组合,生成该组合中event列缺失的日期,日期范围为survey日期回溯31天内(例如id=1且survey='2023-05-05'时,event需包含2023-05-04至2023-04-04的所有日期) - 新生成行的
col1、col2、col3列值为NaN - 新生成行的
nps、target、score列值与对应id+survey组合的原有值保持一致
实现步骤
1. 转换日期列类型
先将survey和event列转为datetime类型,方便后续日期运算:
df['survey'] = pd.to_datetime(df['survey']) df['event'] = pd.to_datetime(df['event'])
2. 分组生成缺失日期行
按id和survey分组,为每个组生成完整日期范围,对比原有数据找出缺失日期并生成新行:
# 定义分组处理函数 def fill_missing_dates(group): # 获取当前组的survey基准日期 survey_date = group['survey'].iloc[0] # 生成回溯31天的日期范围(不含survey当天) date_range = pd.date_range(end=survey_date - pd.Timedelta(days=1), periods=31) # 提取当前组已存在的event日期 existing_events = set(group['event'].dropna()) # 筛选出缺失的日期 missing_dates = [date for date in date_range if date not in existing_events] # 构造缺失日期对应的新行 new_rows = pd.DataFrame({ 'id': group['id'].iloc[0], 'nps': group['nps'].iloc[0], 'target': group['target'].iloc[0], 'score': group['score'].iloc[0], 'survey': survey_date, 'event': missing_dates, 'col1': None, 'col2': None, 'col3': None }) # 合并原有行与新生成行 return pd.concat([group, new_rows], ignore_index=True) # 分组应用函数得到结果 result_df = df.groupby(['id', 'survey'], group_keys=False).apply(fill_missing_dates)
3. 可选:转回字符串日期类型
如果需要将日期列转回原有的object(字符串)格式,执行以下代码:
result_df['survey'] = result_df['survey'].dt.strftime('%Y-%m-%d') result_df['event'] = result_df['event'].dt.strftime('%Y-%m-%d')
示例输出(部分)
print(result_df.head()) # 输出结果示例: # id nps target score survey event col1 col2 col3 # 0 1 2 1 0.33 2023-10-10 2023-09-25 1.0 20.0 11.0 # 1 1 2 1 0.33 2023-10-10 2023-10-04 0.0 10.0 10.0 # 2 1 2 1 0.33 2023-10-10 2023-10-09 NaN NaN NaN # 3 1 2 1 0.33 2023-10-10 2023-10-08 NaN NaN NaN # ...
内容的提问来源于stack exchange,提问作者dingaro
相关产品推荐
相关产品推荐

