【问题标题】:Create DataFrame column from a groupby从 groupby 创建 DataFrame 列
【发布时间】:2020-10-14 19:57:40
【问题描述】:

假设我有一个类似的 DataFrame

import pandas as pd
df = pd.DataFrame({
    'Id'    : [1,2,3,4,5,6,7,8,9],
    'Group' : [1,1,2,2,2,2,3,3,3],
    'Value_to_compare' : [2,1,5,8,2,3,10,23,17],
    'Other_value' : [0,3,2,6,3,4,2,7,1]
})

我想创建一个新列,比如Value_of_Highest,显示在其Group 中具有最高Value_to_compare 的元素的每一行Other_value。例如,这里:

  • 组 1 有 2 个元素,其最高的 Value_to_compare 为 2,Id = 1,其中Other_value 为 0
  • 第 2 组有 4 个元素,最高 Value_to_compare 为 8,Id = 4,其中Other_value 为 6
  • 第 3 组有 3 个元素,最高 Value_to_compare 为 23,Id = 8,其中Other_value 为 7

所以我想加一列让df变成

这是我知道的最好的方法:

def my_func(x):
    x = x.sort_values('Value_to_compare',ascending = False)
    Value_of_Highest = x.head(1)['Other_value'].values[0]
    return pd.Series([Value_of_Highest], index=['Value_of_Highest']) 

grouped = df.groupby('Group').apply(my_func).reset_index()

df = df.merge(grouped)

我很确定在 Python/Pandas 中有一种更优雅、更有效的方法。

编辑:在@CameronRiddell 第一次回答后,我意识到我的示例存在缺陷。我更正了它,@CameronRiddell 编辑了他的答案,效果很好。

【问题讨论】:

    标签: python-3.x pandas dataframe pandas-groupby


    【解决方案1】:

    本质上这是groupby 和transform 的一个很好的应用,使用来自groupby 对象的变换将一个函数应用到每个组,然后返回一个与该组相同大小的Series 或DataFrame。这导致 DataFrame/Series 的形状与沿 groupby 轴的原始形状相同。 (例如,在您的情况下,groupby/transform 的结果将具有与原始数据框相同的行数)。

    df["Value_of_Highest"] = df.groupby("Group")["Value_to_compare"].transform("max")
    
    print(df)
    
       Id  Group  Value_to_compare  Other_value  Value_of_Highest
    0   1      1                 2            0                 2
    1   2      1                 1            3                 2
    2   3      2                 5            2                 8
    3   4      2                 8            6                 8
    4   5      2                 2            3                 8
    5   6      2                 3            4                 8
    6   7      3                10            2                23
    7   8      3                23            7                23
    8   9      3                17            1                23
    
    • df.groupby("Group"):按我们的“组”列对数据框进行分组
    • ["Value_to_compare"]:从每个组中,选择“Value_to_compare”列
    • .transform("max"):获取每组我们选中列的最大值。然后返回一个与组具有相同行数的系列

    编辑:要获得基于最大值位置的值,我们使用idxmax()。这将返回出现最大值/最小值的位置。所以对于我们的用例:

    • 我们将按“Group”分组并选择“Value_to_compare”列
    • 然后我们得到“Value_to_compare”最大值的索引
    highest_vtc_indices = df.groupby("Group")["Value_to_compare"].idxmax()
    
    print(highest_vtc_indices)
    Group
    1    0
    2    3
    3    7
    Name: Value_to_compare, dtype: int64
    

    0、3、7对应每组中“Value_to_compare”的最大值出现的行ID。

    现在我们知道这些最大值发生在哪一行:

    • 我们需要对原始数据框进行子集化,以在每一行中获取“Other_value”
    • 我们还需要获取与这些行关联的“组”列,以便我们以后可以正确对齐这些值
    # Obtain "Group" & "Other_value" at rows 0, 3, 7
      # which were the rows for each highest Value_to_compare per group
    highest_other_values = df.loc[highest_vtc_indices, ["Group", "Other_value"]]
    
    # Rename Other_value to Value_of_Highest
    highest_other_values = highest_other_values.rename(columns={"Other_value": "Value_of_Highest"})
    
    print(highest_other_values)
       Group  Value_of_Highest
    0      1                 0
    3      2                 6
    7      3                 7
    

    现在我们已经有了与每个组的最大“Value_to_compare”相对应的“Other_value”,我们将使用merge 将新的较小数据帧与原始数据帧对齐。这将在原始数据帧的“组”列中广播“Value_of_Highest”。

    # Merge this new dataframe back to our old one to broadcast "Value_of_Highest" across each group
    final = df.merge(highest_other_values, on="Group")
    
    print(final)
       Id  Group  Value_to_compare  Other_value  Value_of_Highest
    0   1      1                 2            0                 0
    1   2      1                 1            3                 0
    2   3      2                 5            2                 6
    3   4      2                 8            6                 6
    4   5      2                 2            3                 6
    5   6      2                 3            4                 6
    6   7      3                10            2                 7
    7   8      3                23            7                 7
    8   9      3                17            1                 7
    

    【讨论】:

    • 哇!我想你救了我的代码伙伴!!!非常感谢!
    • 但这并不完全是这样,因为您复制了 Value_to_compare 而不是 Other_value。
    • CameronRiddell 我意识到我的例子并没有完全反映我的要求。我已经编辑,所以它显示来自Other_value 而不是Value_to_compare 的值。我还是迷路了,你能帮忙吗?
    • 我已经更新了我的答案来解决这个编辑问题! (保留我原来的答案并将新的答案放在它下面)
    • 太好了,非常感谢!下次我需要这种东西时,我会考虑idmax()。 :)
    猜你喜欢
    • 2020-09-23
    • 2019-02-08
    • 1970-01-01
    • 1970-01-01
    • 2021-03-14
    • 2017-02-17
    • 2019-12-31
    • 1970-01-01
    相关资源
    最近更新 更多