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