【问题标题】:Pandas groupby multiple keys selecting unique values and transformingPandas groupby 多个键选择唯一值并转换
【发布时间】:2016-08-12 00:22:42
【问题描述】:

我有一个数据框 df=

Owner     Manager     Date      Hours  City
 John      Jerry       1/2/16     10    LA
 John      Jerry       1/2/16     10    SF
 Mary      Jerry       1/2/16     9     LA
 Zach      Joe         1/3/16     5     SD
 Wendy     Joe         1/3/16     4     SF
 Hal       Joe         1/4/16     2     SD

... 100,000 个条目

我想按“经理”和“日期”分组,然后选择“所有者”的唯一值并对该选择的“小时”求和,最后将总和转换为新列“小时_by_经理”。

我想要的输出是:

Owner     Manager     Date      Hours  City   Hours_by_Manager
   John      Jerry       1/2/16     10    LA   19
   John      Jerry       1/2/16     10    SF   19
   Mary      Jerry       1/2/16     9     LA   19
   Zach      Joe         1/3/16     5     SD   9
   Wendy     Joe         1/3/16     4     SF   9
   Hal       Joe         1/4/16     2     SD   2

我尝试像这样使用 pandas 'groupby':

df['Hours_by_Manager']=df.groupby(['Manager','Date'])['Hours'].transform(lambda x: sum(x.unique()))

这给了我想要的东西,但这只是因为“所有者”之间的小时值不同。我正在寻找的是这样的: df['Hours_by_Manager']=df.groupby(['Manager','Date'])['Owner'].unique()['Hours']transform(lambda x: sum(x)) 这显然在语法上是不正确的。我知道我可以使用 for 循环,但我想保持向量化。有什么建议吗?

【问题讨论】:

  • 假设有另一行以Mary 作为所有者,相同的经理和日期,但Hours 的数量不同,比如19。结果应该是什么?特别是 John 的结果应该是什么?
  • 小时与“所有者”在特定“日期”的工作时间相关联。 “所有者”始终与特定的“经理”相关联。所以玛丽在给定日期永远不会有不同的小时数。从这个意义上说,Hours 的值将是多余的。这就是为什么 John 和 Mary 的两个实例的“Hours_by_Manager”的结果都是 19,因为它们与经理 Jerry 相关联。

标签: pandas transform unique grouping


【解决方案1】:
import pandas as pd
df = pd.DataFrame({'City': ['LA', 'SF', 'LA', 'SD', 'SF', 'SD'],
    'Date': ['1/2/16', '1/2/16', '1/2/16', '1/3/16', '1/3/16', '1/4/16'],
    'Hours': [10, 10, 9, 5, 4, 2],
    'Manager': ['Jerry', 'Jerry', 'Jerry', 'Joe', 'Joe', 'Joe'],
    'Owner': ['John', 'John', 'Mary', 'Zach', 'Wendy', 'Hal']})

uniques = df.drop_duplicates(subset=['Hours','Owner','Date'])
hours = uniques.groupby(['Manager', 'Date'])['Hours'].sum().reset_index()
hours = hours.rename(columns={'Hours':'Hours_by_Manager'})
result = pd.merge(df, hours, how='left')
print(result)

产量

  City    Date  Hours Manager  Owner  Hours_by_Manager
0   LA  1/2/16     10   Jerry   John                19
1   SF  1/2/16     10   Jerry   John                19
2   LA  1/2/16      9   Jerry   Mary                19
3   SD  1/3/16      5     Joe   Zach                 9
4   SF  1/3/16      4     Joe  Wendy                 9
5   SD  1/4/16      2     Joe    Hal                 2

解释:

给定Date 上的Owner 工作于Hours 的唯一编号。所以让我们首先创建一个唯一的['Hours','Owner','Date'] 行表:

uniques = df.drop_duplicates(subset=['Hours','Owner','Date'])
# alternatively, uniques = df.groupby(['Hours','Owner','Date']).first().reset_index()
#   City    Date  Hours Manager  Owner
# 0   LA  1/2/16     10   Jerry   John
# 2   LA  1/2/16      9   Jerry   Mary
# 3   SD  1/3/16      5     Joe   Zach
# 4   SF  1/3/16      4     Joe  Wendy
# 5   SD  1/4/16      2     Joe    Hal

现在我们可以按['Manager', 'Date'] 分组并对Hours 求和:

hours = uniques.groupby(['Manager', 'Date'])['Hours'].sum().reset_index()
  Manager    Date  Hours
0   Jerry  1/2/16     19
1     Joe  1/3/16      9
2     Joe  1/4/16      2

hours['Hours'] 列包含我们想要在df['Hours_by_Manager'] 中的值。

hours = hours.rename(columns={'Hours':'Hours_by_Manager'})

所以现在我们可以合并dfhours来得到想要的结果:

result = pd.merge(df, hours, how='left')
#   City    Date  Hours Manager  Owner  Hours_by_Manager
# 0   LA  1/2/16     10   Jerry   John                19
# 1   SF  1/2/16     10   Jerry   John                19
# 2   LA  1/2/16      9   Jerry   Mary                19
# 3   SD  1/3/16      5     Joe   Zach                 9
# 4   SF  1/3/16      4     Joe  Wendy                 9
# 5   SD  1/4/16      2     Joe    Hal                 2

【讨论】:

  • 这行得通,谢谢!我不明白对 reset_index() 的调用在做什么?
  • uniques.groupby(['Manager', 'Date'])['Hours'].sum() 返回一个带有MultiIndex 的系列。但是pd.merge 需要 2 个数据帧。因此,在期待调用pd.merge 时,我通过调用reset_index 将Series 转换为DataFrame。如果您在 Python 解释器中处理上述代码,您将能够轻松地进行实验并查看 reset_index 的效果。
  • 我明白了!再次感谢!我怎样才能给你一个金徽章:)
猜你喜欢
  • 1970-01-01
  • 2023-03-30
  • 1970-01-01
  • 1970-01-01
  • 2013-02-19
  • 2023-03-31
  • 2021-04-09
相关资源
最近更新 更多