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

在Python DataFrame中基于个体分数匹配对应国家日期的下一个更大四分位数得分

解决方案:为每个Score匹配对应分组的下一个更大Q_Score

你遇到的问题确实没法用简单的pd.merge直接解决,因为需要做条件匹配(找到比当前Score大的最小Q_Score),而不是等值匹配。下面我会提供两种可行的方案,分别适合小数据量和大数据量的场景。

先确认数据(修正输入误差)

首先看你提供的df2数据,看起来是输入时的排版问题——每个国家应该对应4个四分位数(Q1-Q4),而不是按日期分散。我先修正df2的结构,确保每个国家的Q_Score是完整的一组:

import pandas as pd

# 构造你的df1
df1_data = [
    ["20220102", "A", "US", 12.6],
    ["20220103", "A", "US", 11.3],
    ["20220104", "A", "US", 13.2],
    ["20220105", "A", "US", 14.5],
    ["20220102", "B", "US", 9.8],
    ["20220103", "B", "US", 19.8],
    ["20220104", "B", "US", 12.3],
    ["20220105", "B", "US", 15.1],
    ["20220102", "C", "GB", 13.5],
    ["20220103", "C", "GB", 14.5],
    ["20220104", "C", "GB", 11.5],
    ["20220105", "C", "GB", 14.8],
]
df1 = pd.DataFrame(df1_data, columns=["Date", "ID", "C", "Score"])

# 构造修正后的df2(每个国家对应4个四分位数)
df2_data = [
    ["US", 1, 10],
    ["US", 2, 13],
    ["US", 3, 16],
    ["US", 4, 20],
    ["GB", 1, 12],
    ["GB", 2, 13],
    ["GB", 3, 14],
    ["GB", 4, 15],
]
df2 = pd.DataFrame(df2_data, columns=["C", "Q", "Q_Score"])

如果你的df2确实是每个日期+国家都有独立的四分位数,只需要在后续步骤中把分组键从C改成["Date", "C"]即可。


方案1:自定义函数+Apply(适合小数据量)

这种方法逻辑直观,容易理解,适合数据量不大的场景:

步骤1:定义匹配函数

写一个函数,输入当前Score和该国家的Q_Score列表,返回第一个比Score大的Q_Score;如果Score比所有Q_Score都大,就返回最大的Q_Score:

def find_next_higher(score, q_scores):
    sorted_q = sorted(q_scores)  # 确保Q_Score从小到大排序
    for q in sorted_q:
        if q > score:
            return q
    return sorted_q[-1]  # 所有Q都小于等于Score时返回最大的

步骤2:构建国家-Q_Score映射字典

把df2按国家分组,得到每个国家对应的Q_Score列表:

country_q_map = df2.groupby("C")["Q_Score"].apply(list).to_dict()

步骤3:生成Q_Score列

用apply遍历df1的每一行,调用函数匹配对应的Q_Score:

df1["Q_Score"] = df1.apply(lambda row: find_next_higher(row["Score"], country_q_map[row["C"]]), axis=1)
df3 = df1.copy()

此时df3就是你想要的结果,打印验证:

Date ID   C  Score  Q_Score
0  20220102  A  US   12.6       13
1  20220103  A  US   11.3       13
2  20220104  A  US   13.2       16
3  20220105  A  US   14.5       16
4  20220102  B  US    9.8       10
5  20220103  B  US   19.8       20
6  20220104  B  US   12.3       13
7  20220105  B  US   15.1       16
8  20220102  C  GB   13.5       14
9  20220103  C  GB   14.5       15
10 20220104  C  GB   11.5       12
11 20220105  C  GB   14.8       15

方案2:Merge+Groupby(适合大数据量)

apply的效率较低,如果你的数据量很大,推荐用这种基于Pandas原生分组的方法,避免逐行遍历:

步骤1:合并两个DataFrame

先把df1和df2按国家合并,让每个Score都对应到该国家的所有Q_Score:

merged = df1.merge(df2, on="C", how="left")

步骤2:标记符合条件的Q_Score

新增一列标记哪些Q_Score大于当前Score:

merged["is_higher"] = merged["Q_Score"] > merged["Score"]

步骤3:分组筛选目标Q_Score

按df1的唯一行标识(Date+ID+C+Score)分组,筛选出符合条件的Q_Score,取最小的;如果没有符合条件的,就取最大的Q_Score:

df3 = merged.groupby(["Date", "ID", "C", "Score"]).apply(
    lambda x: x[x["is_higher"]]["Q_Score"].min() if x["is_higher"].any() else x["Q_Score"].max()
).reset_index(name="Q_Score")

这个方法的效率比apply高很多,适合处理百万级以上的数据。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.27 15:03:14