You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于最近日期且时差1年内填充DataFrame中的NaN值

问题描述

现有如下DataFrame:

name     score   date
0      Alice    22.0    2020-12-31
15     Alice    4.0     2005-12-31
5      Alice    1.0     2003-12-31
10     Alice    NaN     2000-12-31
6      Bob      8.0     2001-11-02
16     Bob      1.0     2004-11-02
11     Bob      5.0     2003-11-02
1      Bob      45.0    1980-11-02
12     Chuck    9.0     2003-12-03
2      Chuck    4.0     2015-12-03
7      Chuck    9.0     2001-12-03
17     Chuck    2.0     2004-12-03
18     Daren    3.0     2004-03-13
21     Daren    89.0    2015-08-13
3      Daren    NaN     2015-03-13
20     Daren    12.0    2015-05-13
8      Daren    5.0     2015-03-17
13     Daren    93.0    2003-03-13
14     Elisa    11.0    2003-01-24
9      Elisa    19.0    2001-01-24
19     Elisa    23.0    2004-01-24
4      Elisa    16.0    2010-01-24

其中部分score值为NaN,需按以下规则替换:

  • 对每个NaN,在同一name分组下,找到与该NaN对应date时间差最小且时间差在1年(365天)内的非NaN score值进行填充
  • 若同一name下没有符合时间条件的非NaN值,则保留NaN

示例:Daren的NaN会被替换为5,Alice的NaN保留。

重现该DataFrame的代码如下:

import numpy as np
import pandas as pd
import datetime

data = {"name": ['Alice', 'Bob', 'Chuck', 'Daren', 'Elisa', 'Alice', 'Bob', 'Chuck', 'Daren', 'Elisa','Alice', 'Bob', 'Chuck', 'Daren', 'Elisa','Alice', 'Bob', 'Chuck', 'Daren', 'Elisa','Daren','Daren'],
        "score": [22,45,4,np.nan,16,1,8,9,5,19,np.nan,5,9,93,11,4,1,2,3,23,12,89],
        "date": ['31/12/2020','11/02/1980','12/03/2015','13/03/2015','24/01/2010','31/12/2003','11/02/2001','12/03/2001','17/03/2015','24/01/2001','31/12/2000','11/02/2003','12/03/2003','13/03/2003','24/01/2003','31/12/2005','11/02/2004','12/03/2004','13/03/2004','24/01/2004','13/05/2015','13/08/2015']}
df = pd.DataFrame(data = data)
df['date'] = pd.to_datetime(df['date'])
df.sort_values(by='name')
解决方案

通过分组遍历缺失值,筛选同组内符合时间条件的记录并取最近时间对应的score填充,代码如下:

def fill_missing_score(group):
    # 遍历当前分组内所有score为NaN的行
    for idx, row in group[group['score'].isna()].iterrows():
        target_date = row['date']
        # 筛选同组内score非空且时间差在365天内的候选记录
        candidates = group[(group['score'].notna()) & 
                          ((group['date'] - target_date).abs() <= pd.Timedelta(days=365))]
        if not candidates.empty:
            # 计算时间差绝对值,找到最近时间对应的score
            candidates['time_diff'] = (candidates['date'] - target_date).abs()
            closest_score = candidates.loc[candidates['time_diff'].idxmin(), 'score']
            group.loc[idx, 'score'] = closest_score
    return group

# 按name分组处理后重置索引
filled_df = df.groupby('name').apply(fill_missing_score).reset_index(drop=True)
print(filled_df)

结果验证:

  • Daren的NaN(对应date2015-03-13)会匹配到同组内2015-03-17的score=5,时间差4天符合条件,填充为5
  • Alice的NaN(对应date2000-12-31)同组内最近记录的时间差超过365天,保留NaN

内容的提问来源于stack exchange,提问作者You_Donut

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 09:55:09