python pandas groupby / apply:到底传递给apply函数的是什么?

时间:2019-09-01 16:56:13

标签: python pandas dataframe pandas-groupby pandas-apply

此处是Python新手。我试图了解pandas groupby和应用方法的工作方式。我发现了一个简单的示例,this,粘贴在下面:

import pandas as pd

ipl_data = {'Team': ['Riders', 'Riders', 'Devils', 'Devils', 'Kings',
   'kings', 'Kings', 'Kings', 'Riders', 'Royals', 'Royals', 'Riders'],
   'Rank': [1, 2, 2, 3, 3,4 ,1 ,1,2 , 4,1,2],
   'Year': [2014,2015,2014,2015,2014,2015,2016,2017,2016,2014,2015,2017],
   'Points':[876,789,863,673,741,812,756,788,694,701,804,690]}

df = pd.DataFrame(ipl_data)

数据帧df如下所示:

      Team  Rank  Year  Points
0   Riders     1  2014     876
1   Riders     2  2015     789
2   Devils     2  2014     863
3   Devils     3  2015     673
4    Kings     3  2014     741
5    kings     4  2015     812
6    Kings     1  2016     756
7    Kings     1  2017     788
8   Riders     2  2016     694
9   Royals     4  2014     701
10  Royals     1  2015     804
11  Riders     2  2017     690

到目前为止,太好了。然后,我想转换我的数据,以便每个团队组仅保留“积分”列中的第一个元素。首先检查了df['Points'][0]确实确实给了我Points的第一个df元素,然后我尝试了此操作:

df.groupby('Team').apply(lambda x : x['Points'][0])

认为x函数的参数lambda是另一个熊猫数据框。但是,python会产生错误:

File "pandas/_libs/index.pyx", line 81, in pandas._libs.index.IndexEngine.get_value
File "pandas/_libs/index.pyx", line 89, in pandas._libs.index.IndexEngine.get_value
File "pandas/_libs/index.pyx", line 132, in pandas._libs.index.IndexEngine.get_loc
File "pandas/_libs/hashtable_class_helper.pxi", line 987, in pandas._libs.hashtable.Int64HashTable.get_item
File "pandas/_libs/hashtable_class_helper.pxi", line 993, in pandas._libs.hashtable.Int64HashTable.get_item
KeyError: 0

似乎与HashTable有关,但是我不明白为什么。然后,我认为也许传递给lambda的不是数据帧,所以我运行了此代码:

df.groupby('Team').apply(lambda x : (type(x), x.shape))

输出:

Team
Devils    (<class 'pandas.core.frame.DataFrame'>, (2, 4))
Kings     (<class 'pandas.core.frame.DataFrame'>, (3, 4))
Riders    (<class 'pandas.core.frame.DataFrame'>, (4, 4))
Royals    (<class 'pandas.core.frame.DataFrame'>, (2, 4))
kings     (<class 'pandas.core.frame.DataFrame'>, (1, 4))
dtype: object

IIUC显示,lambda的参数确实是一个熊猫数据框,其中包含df的每个团队的子集。

我知道我可以通过运行获得期望的结果:

df.groupby('Team').apply(lambda x : x['Points'].iloc[0])

我只想了解apply函数中df['Points'][0]为何起作用而x['Points'][0]不起作用的原因。谢谢您的阅读!

3 个答案:

答案 0 :(得分:2)

调用mysql> ALTER TABLE mytable DROP PARTITION p20190101; Query OK, 0 rows affected (6 min 25.25 sec) 时,实际上是由Team切分数据帧,并将每个块传递给lambda函数:

df.groupby('Team').apply(lambda x: ...)

Team Rank Year Points 0 Riders 1 2014 876 1 Riders 2 2015 789 8 Riders 2 2016 694 11 Riders 2 2017 690 ------------------------------ 2 Devils 2 2014 863 3 Devils 3 2015 673 ------------------------------ 4 Kings 3 2014 741 6 Kings 1 2016 756 7 Kings 1 2017 788 ------------------------------ 5 kings 4 2015 812 ------------------------------ 9 Royals 4 2014 701 10 Royals 1 2015 804 之所以有效,是因为您告诉熊猫“获取df['Points'][0]系列的标签0处的值”。

Points不起作用,因为只有1个块(.apply(lambda x: x['Points'][0]))的标签为0。因此,您会收到“密钥错误”。


话虽这么说,Riders是通用的,所以与内置的矢量化聚合函数相比,它相当慢。您可以使用apply

first

答案 1 :(得分:1)

Apply函数接受每一行并处理数据,因此Apply确实不理解您要传递给它的索引(如[0]),因此会出错。它与df一起使用,因为索引保持与df一起使用。

您可以尝试类似的方法以使每个团队都获得第一分。

/etc/puppetlabs/code/environments/production/

输出:

public void shellSort(Comparable arr[], int size, int h, int x) {
        while (h >= 1) {
            for (int i = 0; i <= size - h; i++) {
                for (int j = i; j < size-h && (arr[j].compareTo(arr[j+h]) > 0); j += h)
                    swap(arr, j, j+h);      
            }
            h = 3*(--x) + 1;
        }
    }

如果需要保留最大/最小点数行,可以在删除重复项之前对df进行排序。希望有帮助。

答案 2 :(得分:0)

对于标题问题,

agroupby = df.groupby(...)
help( agroupby.apply )  # or in IPython xx.<tab> for help( xx )
<块引用>

pandas.core.groupby.generic.DataFrameGroupBy 实例的apply(func, *args, **kwargs) 方法

按组应用函数 func 并将结果组合在一起。

传递给 apply 的函数必须将数据帧作为它的第一个 参数并返回数据帧、系列或标量。 apply 会 然后注意将结果合并成一个 数据框或系列。