编辑:
我需要apply函数,它从几个复杂的计算中返回几个值。我可以在元组中返回这些值,因此groupby-apply操作的结果将是一个以组名作为索引而元组作为值的系列。我希望它能返回一个DataFrame,所以我可以保留所有pandas的功能和灵活性。
通常,groupby-apply操作的结果将是一个系列在应用返回1值的情况下。在应用返回2个或更多值的情况下,我希望结果是一个数据帧。所以我的问题是如何做到这一点。有关更多详细信息和示例,请参阅原始版本
原文问:
我有一个包含许多列和组的数据框。我试图通过groupby-apply机制进行分组操作,并且每个组只检索2个值。目前,我为每个组返回一个元组(例如return (a,b)
),因此Im得到的结果是一个系列,其中组名称作为索引,tupels作为值。
这对我来说不是最好的输出,因为我接下来需要按照其中一个值进行排序,并且通常这种方式会丢失大部分DataFrame和Series功能。
我想要取回的是一个带有列' a'的数据框架。和' b'。
例如,假设a有一个大的数据帧df看起来像这样:Out[123]:
ID1 ID2 score
0 6073165338_1 6073165338 100
1 6073165338_1 6073165338 89
2 6073165338_1 6073165338 87
3 6073165338_1 6073165338 65
4 6073165338_1 6073165338 62
我想按ID1对其进行分组,并为每个组返回ID2(对于每个ID1组都是相同的) 和前3个参赛作品的平均分。我可以这样做:
def calc(grp):
return grp.ID2.iloc[0],grp.score[:2].mean()
df.groupby('ID1').apply(calc)
的结果应该是ID1组作为索引的系列,以及带有2个元素作为值的元组:
6073165338_1(6073165338,94.5)
我希望输出是一个具有相同索引的数据帧,两个值作为数据框中的列,因此我可以轻松地保持分析。
我该怎么做?
答案 0 :(得分:1)
好的,我有两个解决方案。第一个可能更好,我仍然感谢专家的评论。第一个选项是让应用函数返回一个元组,然后将元组序列转换为DataFrame:
s = x.groupby('ID1').apply(calc)
DataFrame(s.tolist(),index = s.index,columns = ['ID2','top3avg'])
这导致:
Out[156]:
ID2 top3avg
ID1
6073165338_1 6073165338 94.5
第二个是使用返回的元组上的dataframe构造函数返回数据帧:
def calc(grp):
return DataFrame([(grp.ID2.iloc[0],grp.score[:2].mean())],columns=['ID2','top3avg'])
x.groupby('ID1').apply(calc)
的结果现在是一个数据框:
ID2 top3avg
ID1
6073165338_1 0 6073165338 94.5
第一个选项似乎更好:
答案 1 :(得分:0)
根据编辑过的问题,也许这就是你要找的东西。在apply调用结果中返回一个系列被整理成一个数据框(猜测这就是你要找的东西)
返回元组
In [721]: x.groupby('ID1').apply(lambda df: (df['ID2'].irow(0), df['score'].irow(0)))
Out[721]:
ID1
6073165338_1 (6073165338, 100)
dtype: object
返回一个系列
In [720]: x.groupby('ID1').apply(lambda df: pd.Series({'c1':df['ID2'].irow(0), 'c2':df['score'].irow(0)}))
Out[720]:
c1 c2
ID1
6073165338_1 6073165338 100
在第二个示例中,结果位于数据帧
中答案 2 :(得分:0)
首先,看起来你的例子平均超过2个元素,而不是3 - (100 + 89 + 87)/ 3 = 92,(100 + 89)/ 2 = 94.5。
至于你的例子,我认为可以通过在数据帧上获得简单的mean()来完成,其中每个组只剩下前3行。例如,像这样:
df.groupby('ID1').head(3).groupby('ID1').mean()
示例:
>>> df = pd.DataFrame({"ID1":['6073165338_1']*5 + [11111] * 6, "ID2":[6073165338 ]*5 + [22222] * 6, "score":[100,89,87,65,62] + [1, 2, 3, 4, 5, 6]})
>>> df
ID1 ID2 score
0 6073165338_1 6073165338 100
1 6073165338_1 6073165338 89
2 6073165338_1 6073165338 87
3 6073165338_1 6073165338 65
4 6073165338_1 6073165338 62
5 11111 22222 1
6 11111 22222 2
7 11111 22222 3
8 11111 22222 4
9 11111 22222 5
10 11111 22222 6
>>> df.groupby('ID1').head(3).groupby('ID1').mean()
ID2 score
ID1
11111 22222 2
6073165338_1 6073165338 92