Python 3.x Python:groupby一列,只在另一列中聚合,但获取相应的数据

Python 3.x Python:groupby一列,只在另一列中聚合,但获取相应的数据,python-3.x,pandas,pandas-groupby,aggregate,Python 3.x,Pandas,Pandas Groupby,Aggregate,我已经看到了许多其他相关的SO问题,如和,但它们似乎并不完全是我想要的。假设我有这样一个数据帧: 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.

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

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()
现在我想做的是这样的:

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()
问题在于,结果计算所有列(不是
父csn
)的最小值,并生成:

grp_df
            patient  child csn  days
parent csn                          
0                 0         10     3
1                 0         12     4
2                 1         20     4
您可以看到,对于第一行,
days
编号和
子csn
编号不再像分组之前那样位于同一行。以下是我想要的输出:

grp_df
            patient  child csn  days
parent csn                          
0                 0         11     3
1                 0         13     4
2                 1         20     4
我怎么能得到这个?我有迭代数据帧的代码,我认为它会工作,但是当所有的东西都出来时,它会很慢,即使是Cython。我觉得这应该是显而易见的,但我觉得不是这样

我也研究了这个问题,但将
子csn
放在groupby列表中是行不通的,因为
子csn
天数而变化

这个问题似乎更有可能,但我觉得解决方案不是很直观

这个问题似乎也有可能,但答案不是很直观,而且我确实希望每个
父csn
只对应一行

另一个详细信息:包含最小<代码>天数值的行可能不唯一。在这种情况下,我只想要一排——我不在乎哪一排


非常感谢您的时间

您可以通过数据帧筛选需要使用groupby创建筛选器的行,而不仅仅是使用。groupby:

s = df.groupby('parent csn')['days'].transform('min') == df['days']
df = df[s]
df

Out[1]: 
   patient  parent csn  child csn  days
1        0           0         11     3
3        0           1         13     4
4        1           2         20     4
例如,如果我将
s
放在数据帧中,情况就是这样。然后,您只需筛选
True
行,即每个组的最短天数等于该行的行

Out[2]: 
   patient  parent csn  child csn  days      s
0        0           0         10     5  False
1        0           0         11     3   True
2        0           1         12     6  False
3        0           1         13     4   True
4        1           2         20     4   True

您可以使用groupby而不仅仅是使用。groupby:

s = df.groupby('parent csn')['days'].transform('min') == df['days']
df = df[s]
df

Out[1]: 
   patient  parent csn  child csn  days
1        0           0         11     3
3        0           1         13     4
4        1           2         20     4
例如,如果我将
s
放在数据帧中,情况就是这样。然后,您只需筛选
True
行,即每个组的最短天数等于该行的行

Out[2]: 
   patient  parent csn  child csn  days      s
0        0           0         10     5  False
1        0           0         11     3   True
2        0           1         12     6  False
3        0           1         13     4   True
4        1           2         20     4   True

作为所需的输出,您需要先对值进行
排序
并按
分组

df_final = (df.sort_values(['parent csn', 'patient', 'days', 'parent csn'])
              .groupby('parent csn').first())

Out[813]:
            patient  child csn  days
parent csn
0                 0         11     3
1                 0         13     4
2                 1         20     4

作为所需的输出,您需要先对值进行
排序
并按
分组

df_final = (df.sort_values(['parent csn', 'patient', 'days', 'parent csn'])
              .groupby('parent csn').first())

Out[813]:
            patient  child csn  days
parent csn
0                 0         11     3
1                 0         13     4
2                 1         20     4

您可以通过使用
.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
由此可以看出,组父级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):


您可以通过使用
.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
由此可以看出,组父级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):


由于某些原因,我无法解释您的数据帧具有
object
类型的列。此解决方案仅适用于数值列

df.days = df.days.astype(int)
df.iloc[df.groupby('parent csn').days.idxmin()]
输出:


由于某些原因,我无法解释您的数据帧具有
object
类型的列。此解决方案仅适用于数值列

df.days = df.days.astype(int)
df.iloc[df.groupby('parent csn').days.idxmin()]
输出:


这是因为数据帧开始是空的。Pandas不假设列的数据类型中没有任何内容,因此将它们保留为“对象”数据类型(这是最灵活的)。然后,当您通过
.loc
来“填充”列时,它们将保留其“对象”数据类型。在一个不相关的注释中,你也应该使用<代码> .LOC < /C>来回答你的问题,因为<代码> IDxmin()>代码>返回与最小值相关的相应索引。如果索引是“a”、“b”、“c”、“d”、“e”)@ AdRiaKeister--请考虑接受。这是同样的想法,但对其他读者来说信息更丰富,并且在我的解决方案发布之前就发布了。如果你愿意的话,非常好。我可以看出他们或多或少是一样的。你的答案很好,因为代码都在一个地方。@MichaelSzczesny我很感激!我在回答中添加了一个“tldr”,这是因为数据帧开始时是空的。Pandas不假设列的数据类型中没有任何内容,因此将它们保留为“对象”数据类型(这是最灵活的)。然后,当您通过
.loc
来“填充”列时,它们将保留其“对象”数据类型。在一个不相关的注释中,你也应该使用<代码> .LOC < /C>来回答你的问题,因为<代码> IDxmin()>代码>返回与最小值相关的相应索引。如果索引是“a”、“b”、“c”、“d”、“e”)@ AdRiaKeister--请考虑接受。这是同样的想法,但对其他读者来说信息更丰富,并且在我的解决方案发布之前就发布了。如果你愿意的话,非常好。我可以看出他们或多或少是一样的。你的答案很好,因为代码都在一个地方。@MichaelSzczesny我很感激!我在回答中加了一个“tldr”。