首页 > 解决方案 > Python Pandas:按一列分组,仅在另一列中聚合,但取相应数据

问题描述

我已经看到了许多其他相关的 SO 问题,例如thisthis,但它们似乎并不是我想要的。假设我有一个这样的数据框:

import pandas as pd
df = pd.DataFrame(columns=['patient', 'parent csn', 'child csn', 'days'])
df.loc[0] = [0, 0, 10, 5]
df.loc[1] = [0, 0, 11, 3]
df.loc[2] = [0, 1, 12, 6]
df.loc[3] = [0, 1, 13, 4]
df.loc[4] = [1, 2, 20, 4]
df
Out[9]: 
  patient parent csn child csn days
0       0          0        10    5
1       0          0        11    3
2       0          1        12    6
3       0          1        13    4
4       1          2        20    4

现在我想做的是这样的:

grp_df = df.groupby(['parent csn']).min()

问题是结果计算所有列(不是parent csn)的最小值,这会产生:

grp_df
            patient  child csn  days
parent csn                          
0                 0         10     3
1                 0         12     4
2                 1         20     4

您可以看到,对于第一行,days数字和child csn数字不再位于同一行,就像它们在分组之前一样。这是我想要的输出:

grp_df
            patient  child csn  days
parent csn                          
0                 0         11     3
1                 0         13     4
2                 1         20     4

我怎么能得到那个?我有遍历数据框的代码,我认为它会起作用,但是即使使用 Cython,它也很慢。我觉得这应该是显而易见的,但我不这么认为。

我也查看了这个问题,但是将 放在groupbychild csn列表中是行不通的,因为.child csndays

这个问题似乎更有可能,但我没有找到非常直观的解决方案。

这个问题似乎也很可能,但同样,答案不是很直观,而且我确实希望每个parent csn.

另一个细节:包含最小值的行days可能不是唯一的。在那种情况下,我只想要一排 - 我不在乎。

非常感谢您的宝贵时间!

标签: python-3.xpandaspandas-groupbyaggregate

解决方案


您可以通过使用.idxmin()而不是.min()获取索引(行标识符)来执行此操作,其中每个组的“天数”最少:

数据创建:

import pandas as pd

data = [[0, 0, 10, 5],
        [0, 0, 11, 3],
        [0, 1, 12, 6],
        [0, 1, 13, 4],
        [1, 2, 20, 4]]
df = pd.DataFrame(data, columns=['patient', 'parent csn', 'child csn', 'days'])

print(df)
   patient  parent csn  child csn  days
0        0           0         10     5
1        0           0         11     3
2        0           1         12     6
3        0           1         13     4
4        1           2         20     4
day_minimum_row_indices = df.groupby("parent csn")["days"].idxmin()

print(day_minimum_row_indices)
parent csn
0    1
1    3
2    4
Name: days, dtype: int64

从这里你可以看到组父 csn 0 在第 1 行有最少的天数。回顾我们的原始数据框,我们可以看到第 1 行有天 == 3 并且实际上是父最小天数的位置csn == 0。父 csn == 1 在第 3 行有最少天数,依此类推。

我们可以使用行索引子集回到我们的原始数据帧中:

new_df = df.loc[day_minimum_row_indices]

print(new_df)
   patient  parent csn  child csn  days
1        0           0         11     3
3        0           1         13     4
4        1           2         20     4

编辑(tldr):

df.loc[df.groupby("parent csn")["days"].idxmin()]

推荐阅读