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

基于Pandas DataFrame的Location匹配阈值范围筛选异常行

基于Pandas DataFrame的Location匹配阈值范围筛选异常行

嘿,这个需求很明确,我来一步步帮你实现基于Location匹配阈值、筛选异常行的功能,完全适配你提到的「cost列数量可变」的场景!

整体思路

  1. 先从df1中提取每个Location对应的max和min阈值,形成一个映射表
  2. 将这个阈值表和df2合并,让df2的每一行都带上对应Location的阈值
  3. 动态识别所有cost列(不管数量多少)
  4. 检查每一行的cost值是否有超出[min, max]范围的情况,标记异常行
  5. 提取所有异常行组成新的DataFrame

代码实现与解释

首先,我们先把示例数据准备好(你可以直接替换成自己的真实数据):

import pandas as pd

# 创建示例df1
df1 = pd.DataFrame({
    'route_no': ['0010', '0011', '0012', '0013', '0014'],
    'cost_h1': [20, 30, 67, 34, 44],
    'cost_h2': [22, 25, 68, 33, 42],
    'cost_h3': [21, 23, 68, 31, 40],
    'cost_h4': [23, 31, 69, 30, 39],
    'cost_h5': [26, 33, 65, 35, 50],
    'max': [26, 33, 69, 35, 50],
    'min': [20, 23, 67, 31, 39],
    'location': ['NY', 'CA', 'GA', 'MO', 'WA']
})

# 创建示例df2
df2 = pd.DataFrame({
    'route_no': ['0020', '0021', '0023', '0022', '0025', '0030', '0032', '0034'],
    'cost_h1': [19, 31, 66, 34, 41, 19, 37, 40],
    'cost_h2': [27, 22, 67, 33, 42, 26, 31, 41],
    'cost_h3': [21, 23, 68, 31, 40, 20, 31, 39],
    'cost_h4': [24, 30, 70, 30, 39, 24, 20, 39],
    'cost_h5': [20, 33, 65, 35, 50, 20, 35, 50],
    'location': ['NY', 'CA', 'GA', 'MO', 'WA', 'NY', 'MO', 'WA']
})

步骤1:提取阈值映射表

从df1中取出location、max、min三列,并且确保每个location只保留一组阈值(如果df1中同一个location有多行,这里会自动保留第一组,你也可以根据需求改成取均值/最大阈值等):

# 提取每个location对应的阈值,去重确保唯一映射
thresholds = df1[['location', 'max', 'min']].drop_duplicates()

步骤2:合并阈值到df2

用merge操作把阈值表和df2按location关联,确保df2的每一行都拿到对应的阈值:

# 左连接保留df2的所有行,即使没有匹配的location
df2_with_threshold = df2.merge(thresholds, on='location', how='left')

步骤3:动态识别所有cost列

通过列名前缀cost_h来筛选,不管有多少个cost列都能自动识别:

# 筛选所有以cost_h开头的列
cost_cols = [col for col in df2.columns if col.startswith('cost_h')]

步骤4:标记异常行

对每一行的cost值进行检查,只要有一个值超出[min, max]范围,就标记为异常行。同时我们也处理「没有匹配到阈值」的情况(比如df2里有个location在df1中不存在,这时候max/min会是NaN,我们也把这类行标记为异常):

# 检查每个cost值是否超出阈值范围
df2_with_threshold['is_outlier'] = df2_with_threshold.apply(
    lambda row: any(val < row['min'] or val > row['max'] for val in row[cost_cols]),
    axis=1
)

# 补充:把没有匹配到阈值(max/min为NaN)的行也标记为异常
df2_with_threshold['is_outlier'] = df2_with_threshold['is_outlier'] | df2_with_threshold[['max', 'min']].isna().any(axis=1)

步骤5:提取异常行

最后把标记为异常的行筛选出来,去掉临时的标记列:

# 提取所有异常行,并移除标记列
outlier_df = df2_with_threshold[df2_with_threshold['is_outlier']].drop(columns=['is_outlier'])

# 查看结果
print("异常行结果:")
print(outlier_df)

运行结果

执行后你会得到如下异常行(对应示例数据中超出阈值的行):

route_no  cost_h1  cost_h2  cost_h3  cost_h4  cost_h5 location  max  min
0    0020       19       27       21       24       20       NY   26   20
1    0021       31       22       23       30       33       CA   33   23
2    0023       66       67       68       70       65       GA   69   67
5    0030       19       26       20       24       20       NY   26   20
6    0032       37       31       31       20       35       MO   35   31

这个方案完全适配cost列数量变化的场景,不管你有5个还是50个cost列,代码都能自动识别并检查~

备注:内容来源于stack exchange,提问作者S_Scouse

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.23 14:02:50