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

如何在Pandas中按日期差计算到最近圣诞标记行的距离(适配road_id)

按日期差计算每行到最近圣诞节的天数(支持分组与多标记场景)

需求说明

  • 计算数据集中每行到最近圣诞节的天数,按日期差而非行数计算
  • 数据集字段包含:road_id、traffic、date、is_christmas
  • 需支持按road_id分组计算
  • 适配同一日期存在多条圣诞标记(is_christmas=1)的场景

现有尝试方案及问题

1. 循环遍历实现

import pandas as pd
import numpy as np

# 创建示例数据集
df = pd.DataFrame({
    'traffic': [100, 200, 150, 300, 250, 400, 350, 500],
    'date': pd.date_range(start='2021-12-24', periods=8, freq='D'),
    'is_christmas': [0, 1, 0, 0, 0, 1, 0, 0]
})

# 为每行查找最近圣诞节日期
df['nearest_christmas'] = np.nan
for i, row in df.iterrows():
    if row['is_christmas'] == 1:
        df.at[i, 'nearest_christmas'] = 0
    else:
        nearest_christmas_index = (df.loc[df['is_christmas'] == 1, 'date'] - row['date']).abs().idxmin()
        df.at[i, 'nearest_christmas'] = (df.at[nearest_christmas_index, 'date'] - row['date']).days

print(df)

存在问题:

  • 未实现road_id分组逻辑
  • 大型数据集上性能极差,iterrows()循环效率极低

2. Groupby+Transform实现

import pandas as pd

# 创建示例数据集
df = pd.DataFrame({
    'traffic': [100, 200, 150, 300, 250, 400, 350, 500],
    'date': pd.date_range(start='2021-12-24', periods=8, freq='D'),
    'is_christmas': [0, 1, 0, 0, 0, 1, 0, 0]
})

df['nearest_christmas'] = df.groupby('is_christmas')['date'].transform(lambda x: x.diff().abs().dt.days)

print(df)

存在问题:

  • 计算结果完全错误,逻辑方向偏差(按is_christmas分组求日期差不符合需求)
  • 未支持road_id分组

高效正确的Pandas实现方案

以下方案通过分组后提取圣诞日期,利用广播计算最小日期差,同时处理多标记场景:

import pandas as pd
import numpy as np

# 创建包含road_id的示例数据集(含同一日期多圣诞标记)
df = pd.DataFrame({
    'road_id': ['A', 'A', 'A', 'A', 'B', 'B', 'B', 'B', 'B'],
    'traffic': [100, 200, 150, 300, 250, 400, 350, 500, 450],
    'date': pd.date_range(start='2021-12-24', periods=9, freq='D'),
    'is_christmas': [0, 1, 1, 0, 0, 0, 1, 0, 0]
})

# 确保date字段为datetime类型
df['date'] = pd.to_datetime(df['date'])

def calculate_nearest_christmas(group):
    # 提取当前分组内的所有圣诞日期(去重,避免同一日期多标记重复计算)
    christmas_days = group.loc[group['is_christmas'] == 1, 'date'].unique()
    if len(christmas_days) == 0:
        # 分组内无圣诞标记时返回NaN(可根据需求调整)
        return pd.Series([pd.NA]*len(group), index=group.index)
    # 广播计算每行日期到所有圣诞日期的天数差,取绝对值最小的那个
    day_diffs = group['date'].apply(lambda x: np.min(np.abs((christmas_days - x).days)))
    # 圣诞当天的行强制设为0(避免浮点精度问题)
    day_diffs[group['is_christmas'] == 1] = 0
    return day_diffs

# 按road_id分组计算
df['nearest_christmas'] = df.groupby('road_id', group_keys=False).apply(calculate_nearest_christmas)

print(df)

方案说明:

  1. 分组处理:通过groupby('road_id')实现按道路分组计算
  2. 去重圣诞日期:用unique()处理同一日期多条圣诞标记的场景,避免重复计算
  3. 高效日期差计算:利用Pandas的广播特性,避免循环,大幅提升性能
  4. 边界处理:对无圣诞标记的分组返回pd.NA,可根据业务需求调整默认值
  5. 精度保障:强制将is_christmas=1的行设为0,避免浮点计算带来的误差

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 13:05:02