如何在pandas列中获取某个ID的第二高值?

5

我认为这个问题最好通过以下方式进行可视化,给定一个数据框:

val_1          true_val ID      label
-0.0127894447       0.0  1       A
0.9604560385        1.0  2       A
0.0001271985        0.0  3       A
0.0007419337        0.0  3       B
0.3420448566        0.0  2       B
0.1322384726        1.0  4       B

所以我想要的是:

label  ID_val_1_second_highest    ID_true_val_highest
A        3                              2
B        4                              4

我想获取val_1第二高的值和true_val(总是等于1.0)最高的值相对应的ID,然后返回每个标签的两个对应ID。
有没有人知道怎么做?我尝试过:
``` result_at_one = result.set_index('ID').groupby('label').idxmax() ```
这可以让我得到两者的最高值,但我只想要真实标签的最高值,同时获取val_1变量的第二/第三等高的值。
有人把这个链接作为答案: Pandas: Get N largest values and insert NaN values if there are no elements 但是,如果使用那种方法,我需要按标签进行分组。因此,在这种情况下,输出将变为:
 label  true_id     top1_id_val_1             top2_id_val_1         top3_id_val_1
    A   2             2                          3               1
    B   4             2                          4               3

有人知道怎么做吗?


这与之前提出的问题非常类似。点击此处查看原问题。 - Henry Yik
有一个区别,因为在这个问题中是按标签(A、B等)而不是一次性处理所有数据。 - stacksonoverflow
3个回答

3
你可以使用自定义的 apply 函数与 groupby 来达到你想要的结果。
def sorted_maximums(group, nlargest, upto=False):
    # Get the largest IDs in the current group
    largest_ids = group.nlargest(nlargest, "val_1")["ID"]
    index = ["val_1_ID_rank_{}".format(i) for i in range(1, nlargest+1)]
    
    # Drop data if we're only interested in the nlargest value
    #  and none of the IDs leading up to it
    if upto is False:
        largest_ids = largest_ids.iloc[nlargest-1:]
        index = index[-1:]
        
    # Get the ID at the max "true_val"
    true_val_max = group.at[group["true_val"].idxmax(), "ID"]
    index += ["ID_true_val_highest"]

    # Combine our IDs based on val_1 and our ID based on true_val
    data = [*largest_ids, true_val_max]
    return pd.Series(data, index=index)
    
df.groupby("label").apply(sorted_maximums, nlargest=2, upto=False).reset_index()

  label  val_1_ID_rank_2  ID_true_val_highest
0  A     3                2                  
1  B     4                4                      

df.groupby("label").apply(sorted_maximums, nlargest=2, upto=True).reset_index()

  label  val_1_ID_rank_1  val_1_ID_rank_2  ID_true_val_highest
0  A     2                3                2                  
1  B     2                4                4                  

由于根据您的问题我不确定您是否对获取第二大ID(@val_1)感兴趣,还是一次性获取第1、2和3个最高ID @val_1,因此我提供了这两种方法。将upto设为True将执行后者,而将其设为False将执行前者,并仅获取您在@val_1上第1、第2或第3个最高ID。


3

您可以将其分为几个阶段:

# grouping is relatively inexpensive :
grouping = df.groupby("label")

# get second highest val
id_val = grouping.nth(-1)["ID"].rename("ID_val_1_second_highest")

#get highest true val
# you could also do df.true_val.eq(grouping.true_val.transform('max'))
# since we know the highest is 1, I just jumped into it 
    true_val = (df.loc[df.true_val == 1, ["ID", "label"]]
               .set_index("label")
               .rename( columns={"ID": "ID_true_val_highest"}))

 # merge to get output : 
 pd.concat([id_val, true_val], axis=1,).reset_index()

    label   ID_val_1_second_highest ID_true_val_highest
0       A      3                        2
1       B      4                        4

1
聪明 - 我不知道 groupby.nth 方法。 - Yaakov Bressler

1

尝试了几种方法(即排序+排名+融合,透视,使用自定义函数的分组),我得出结论:扩展分组是最佳解决方案(适用于像这样的专门情况):

records = []

# Iterate through your groupby objects
for group_label, group_df in df[["label","ID","val_1"]].groupby("label"):
    # get ranked indices
    rank_idx = group_df["val_1"].rank()
    # extract individual attributes
    ID_true_val_highest = group_df.loc[rank.rank_idx[1], "ID"]
    ID_val_1_second_highest = group_df.loc[rank.rank_idx[2], "ID"]

    # store your observations
    rec = {
        "label":group_label,
        "ID_true_val_highest":ID_true_val_highest,
        "ID_val_1_second_highest":ID_val_1_second_highest,
        }
    records.append(rec)
    
# make into a dataframe
pd.DataFrame.from_records(records)

    label   ID_true_val_highest ID_val_1_second_highest
0   A   2.0 3.0
1   B   2.0 4.0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接