Groupby 并按 pandas 中的最大值过滤

Groupby and filter by max value in pandas

我正在处理如下所示的数据框:(在编辑中添加了 ID 2)

+-------+----+------+------+
| Value | ID | Date | ID 2 |
+-------+----+------+------+
|     1 |  5 | 2012 | 111 |
|     1 |  5 | 2013 | 112 |
|     0 | 12 | 2017 | 113 |
|     0 | 12 | 2022 | 114 |
|     1 | 27 | 2005 | 115 |
|     1 | 27 | 2011 | 116 |
+-------+----+------+-----+

仅使用“值”==“1”(“值为布尔值”)的行,我想按 ID 对数据框进行分组并将字符串“最新”输入到新(空白)列,给出以下内容输出:

+-------+----+------+--------+
| Value | ID | Date | Latest |
+-------+----+------+--------+
|     1 |  5 | 2012 |        |
|     1 |  5 | 2013 | Latest |
|     0 | 12 | 2017 |        |
|     0 | 12 | 2022 |        |
|     1 | 27 | 2005 |        |
|     1 | 27 | 2011 | Latest |
+-------+----+------+--------+

pandas 的语法让我失望,因为我对 Python 还很陌生。

在 R 中,我想我会尝试类似

的东西
df %>% select(Value == "1") %>% group_by(ID) %>% select(max(Date)

但我不确定 Pandas 中的语法...我试图首先 select 通过使用 [=] 满足条件“值 == 1”的行子集18=]

q = df.query('Value == 1')
my_query_index = q.index
my_query_index

这 returns 所有行的索引,但我不确定如何在按 max(date) 分组和过滤之前将其合并到数据框中。

感谢所有帮助。谢谢。

编辑:我使用固定答案如下:

latest = df.query('Value==1').groupby("ID").max("Year").assign(Latest = "Latest")
df = pd.merge(df,latest,how="outer")
df

但我后来意识到一些最大年份是相同的,即可能有 4 行,所有最大年份都是 2017 年。对于决胜局,我需要在组内使用最大 ID 2。我在代码行中添加了 .groupby("ID 2").max("ID 2"),给出

latest = df.query('Value==1').groupby("ID").max("Year").groupby("ID 2").max("ID 2").assign(Latest = "Latest")
df = pd.merge(df,latest,how="outer")
df

但它给我的数据框与我想要的完全不同。

感谢您的帮助,不胜感激。

你可以这样做:

latest = df.query('Value==1').groupby("ID").max("year").assign(Latest = "Latest")
pd.merge(df,latest,how="outer")

   Value  ID  Date  Latest
0      1   5  2012     NaN
1      1   5  2013  Latest
2      0  12  2017     NaN
3      0  12  2022     NaN
4      1  27  2005     NaN
5      1  27  2011  Latest
  1. 'ID' 排序,然后按 'Date'
  2. 排序
  3. 使用duplicated(keep='last')确定每组中的最后一项
  4. loc 分配到正确的位置

df = df.sort_values(['ID', 'Date'])
mask1 = df.Value.eq(1)
mask2 = ~df.ID.duplicated(keep='last')

df.loc[mask1 & mask2, 'Latest'] = 'Latest'

df

   Value  ID  Date  Latest
0      1   5  2012     NaN
1      1   5  2013  Latest
2      0  12  2017     NaN
3      0  12  2022     NaN
4      1  27  2005     NaN
5      1  27  2011  Latest

一个选项是groupby,使用transform获得最大值,然后使用条件语句np.where获得输出:

max_values = df.groupby("ID").Date.transform("max")
df.assign(Latest=np.where(df.Date.eq(max_values) & df.Value.eq(1), "Latest", ""))

   Value  ID  Date  Latest
0      1   5  2012        
1      1   5  2013  Latest
2      0  12  2017        
3      0  12  2022        
4      1  27  2005        
5      1  27  2011  Latest