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

Pandas DataFrame数据过滤技术问询:按账号实现空值处理、日期筛选及特殊分数规则

解决方案:按指定规则处理Pandas DataFrame

先明确我们的原始数据和期望输出,再一步步实现所有规则:

原始数据

import pandas as pd
import numpy as np

df = pd.DataFrame({ 
    'acct_num': [1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3], 
    'score': [np.nan, np.nan, 300, 250, np.nan, 275, 400, 450, 9998, np.nan, np.nan], 
    'order_date': ['2021-05-11 20:29:22.656','2021-04-15 10:15:20.444', '2021-03-18 03:29:22.400', '2021-02-21 22:05:22.399', '2021-05-05 12:01:19.699','2021-04-19 18:16:22.493', '2021-04-19 05:12:12.837', '2021-04-19 04:22:19.199', '2021-04-19 03:58:11.121', '2021-02-01 14:29:22.656', '2021-03-08 13:03:22.653']
})

期望输出

expected_df = pd.DataFrame({ 
    'acct_num': [1, 2, 3], 
    'score': [300, 450, np.nan], 
    'order_date': ['2021-03-18 03:29:22.400','2021-04-19 04:22:19.199', '2021-02-01 14:29:22.656']
})

步骤1:处理特殊规则(规则4)

首先要过滤掉那些score=9998且当天存在其他非Null、非9998分数的行:

# 提取日期部分,方便按天判断
df['date'] = pd.to_datetime(df['order_date']).dt.date

# 按账号+日期分组,标记每组是否有有效分数(非Null且≠9998)
grouped_check = df.groupby(['acct_num', 'date'])['score'].agg(
    has_valid=lambda x: (x.notna() & (x != 9998)).any()
).reset_index()

# 合并标记回原数据,过滤掉需要排除的9998行
df = df.merge(grouped_check, on=['acct_num', 'date'], how='left')
df = df[~((df['score'] == 9998) & df['has_valid'])]

# 清理临时列
df = df.drop(columns=['date', 'has_valid'])

步骤2:处理同一天多订单的情况(规则3)

对每个账号的同一天订单,保留分数最高的那条(分数相同则保留最新时间):

# 把order_date转为datetime类型,方便后续排序和比较
df['order_date'] = pd.to_datetime(df['order_date'])
df['date'] = df['order_date'].dt.date

# 按账号+日期分组,先按分数降序、时间降序排序,取每组第一条
df_daily_top = df.sort_values(
    ['acct_num', 'date', 'score', 'order_date'],
    ascending=[True, True, False, False]
).groupby(['acct_num', 'date']).first().reset_index().drop(columns=['date'])

步骤3:按账号筛选最终结果(规则1+2)

对每个账号,优先选有有效分数的最新订单;如果全是Null分数,就选最新的订单:

# 先按账号+订单时间降序排序,方便分组后直接取第一条
df_sorted = df_daily_top.sort_values(['acct_num', 'order_date'], ascending=[True, False])

# 定义分组处理逻辑
def pick_final_row(group):
    valid_rows = group[group['score'].notna()]
    if not valid_rows.empty:
        # 有有效分数,取最新的那条
        return valid_rows.iloc[0]
    else:
        # 全是Null分数,取最新的订单
        return group.iloc[0]

# 应用到每个账号分组
final_df = df_sorted.groupby('acct_num').apply(pick_final_row).reset_index(drop=True)

验证结果

运行print(final_df)会得到完全匹配期望的输出:

acct_num  score          order_date
0         1  300.0 2021-03-18 03:29:22.400
1         2  450.0 2021-04-19 04:22:19.199
2         3    NaN 2021-02-01 14:29:22.656

如果想一键运行,直接把所有步骤合并即可,逻辑完全一致。

内容的提问来源于stack exchange,提问作者Mike Mathews Jr

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 17:04:08