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

如何高效筛选DataFrame中与至少一个日期间隔≤6个月的行

高效处理百万级日期筛选:保留与至少一个日期间隔≤6个月的行

问题场景

现有包含Name、Address、Date三列的DataFrame:

Name  Address Date
faraz  xyz    2022-01-01
Abdul  abc    2022-06-06
Zara   qrs    2021-02-25

需求:仅保留Date列中与至少一个其他日期间隔不超过6个月的行。示例中Zara的日期与另外两个间隔均超6个月,需删除,最终保留前两行。

原嵌套循环方案在百万级数据下效率极低,iterrows()+内层循环的时间复杂度为O(n*m),完全无法处理大数据量。以下是基于Pandas矢量化操作的最优解决方案:


方案1:基于merge_asof的精准匹配(适合含重复日期的大数据)

利用merge_asof高效找到每个日期的前后最近日期,通过矢量化计算判断间隔是否符合要求,时间复杂度为O(n log n)。

步骤1:预处理日期列

import pandas as pd

# 转换Date列为datetime并排序
df['Date'] = pd.to_datetime(df['Date'])
df_sorted = df.sort_values('Date').reset_index(drop=True)

步骤2:匹配前一个最近日期并计算间隔

# 准备前向匹配数据集
prev_dates = df_sorted[['Date']].rename(columns={'Date': 'prev_date'})

# 按日期反向匹配,找到每个日期的前一个最近日期(容忍183天≈6个月)
df_prev = pd.merge_asof(
    df_sorted,
    prev_dates,
    left_on='Date',
    right_on='prev_date',
    direction='backward',
    tolerance=pd.Timedelta(days=183)
)

# 计算精准月份差
df_prev['months_diff_prev'] = (df_prev['Date'].dt.year - df_prev['prev_date'].dt.year) * 12 + \
                              (df_prev['Date'].dt.month - df_prev['prev_date'].dt.month)
# 无前置日期的行填充为无穷大
df_prev['months_diff_prev'] = df_prev['months_diff_prev'].fillna(float('inf'))

步骤3:匹配后一个最近日期并计算间隔

# 准备后向匹配数据集
next_dates = df_sorted[['Date']].rename(columns={'Date': 'next_date'})

# 按日期正向匹配,找到每个日期的后一个最近日期
df_next = pd.merge_asof(
    df_sorted,
    next_dates,
    left_on='Date',
    right_on='next_date',
    direction='forward',
    tolerance=pd.Timedelta(days=183)
)

# 计算精准月份差
df_next['months_diff_next'] = (df_next['next_date'].dt.year - df_next['Date'].dt.year) * 12 + \
                              (df_next['next_date'].dt.month - df_next['Date'].dt.month)
# 无后置日期的行填充为无穷大
df_next['months_diff_next'] = df_next['months_diff_next'].fillna(float('inf'))

步骤4:筛选符合条件的行

# 合并前后匹配结果
df_combined = df_prev.merge(df_next, on=['Name', 'Address', 'Date'])

# 筛选:前一个或后一个日期间隔≤6个月
filtered_df = df_combined[(df_combined['months_diff_prev'] <= 6) | (df_combined['months_diff_next'] <= 6)]

# 恢复原始顺序(可选)
filtered_df = filtered_df.sort_index().reset_index(drop=True)

方案2:基于唯一日期的快速筛选(重复日期较多时更高效)

先处理唯一日期集合,再映射回原始数据,进一步减少计算量:

import pandas as pd

df['Date'] = pd.to_datetime(df['Date'])

# 获取排序后的唯一日期
unique_dates = pd.Series(df['Date'].sort_values().unique())

# 计算每个日期与前后日期的近似月份差(按平均每月30.44天计算)
prev_diff = (unique_dates - unique_dates.shift(1)).dt.days / 30.44
next_diff = (unique_dates.shift(-1) - unique_dates).dt.days / 30.44

# 筛选有效日期:前后至少有一个间隔≤6个月
valid_dates = unique_dates[(prev_diff.fillna(float('inf')) <= 6) | (next_diff.fillna(float('inf')) <= 6)]

# 过滤原始DataFrame
filtered_df = df[df['Date'].isin(valid_dates)]

关键说明

  • merge_asof是Pandas专为有序键设计的高效合并工具,避免了逐行循环,适合百万级数据处理。
  • 月份差计算可选择精准月份差(年差*12+月差)或近似天数差(除以平均每月天数),按需选择。
  • 重复日期较多时,优先使用方案2,能大幅降低计算开销。

内容的提问来源于stack exchange,提问作者Syed Faraz Khalid

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 12:48:24