在Pandas中使用'apply'(外部定义的函数)

时间:2014-05-26 03:48:22

标签: python pandas

我有一个Dataframe table,如下所示:

year name     prop     sex  soundex
1880 John     0.081541 boy  J500
1880 William  0.080511 boy  W450
....
2008 Elianna  0.000127 girl E450

我尝试按table'year'进行分组,并为每个组访问'name'列中的选择索引。

我的代码如下(假设special_indices已经定义):

def get_indices_func(x):
    name = [x['name'].iloc[y] for y in special_indices]
    return pd.Series(name)


table.groupby(by='year').apply(get_indices_func)

我收到以下错误:

/Users/***/Library/Enthought/Canopy_64bit/User/lib/python2.7/site-packages/pandas/core/index.pyc in get_value(self, series, key)
    722         """
    723         try:
--> 724             return self._engine.get_value(series, key)
    725         except KeyError, e1:
    726             if len(self) > 0 and self.inferred_type == 'integer':

KeyError: 1000 

我做错了什么?我认为我并不真正了解申请(及其表兄弟,聚合和凝聚)的运作方式。如果有人能够解释,我会非常感激!

3 个答案:

答案 0 :(得分:2)

  

我正在努力寻找每年最受欢迎的名字。有没有   聪明的方式去做这个?

有一种方法可以在不进行排序的情况下执行此操作:给定一个像这样的DataFrame:

In [5]: df
Out[5]: 
   year     name      prop   sex soundex
0  1880     John  0.081541   boy    J500
1  1880  William  0.080511   boy    W450
2  2008  Elianna  0.000127  girl    E450

[3 rows x 5 columns]

您可以按年份分组,隔离道具列,应用argmax,然后使用loc选择所需的行:

In [15]: df.loc[df.groupby('year')['prop'].apply(lambda x: x.argmax())]
Out[15]: 
   year     name      prop   sex soundex
0  1880     John  0.081541   boy    J500
2  2008  Elianna  0.000127  girl    E450

[2 rows x 5 columns]

In [19]: df['name'].loc[df.groupby('year')['prop'].apply(lambda x: x.argmax())]
Out[19]: 
0       John
2    Elianna
Name: name, dtype: object

请注意,argmaxloc的使用依赖于具有唯一索引的df。如果DataFrame没有唯一索引,则需要首先使索引唯一:

df.reset_index()

请注意,argmaxO(n)操作,而排序是O(n log n)。即使对于小型DataFrame,速度优势也很明显:

In [125]: %timeit df[['year', 'name']].loc[df.groupby('year')['prop'].apply(lambda x: x.argmax())]
1000 loops, best of 3: 1.07 ms per loop

In [126]: %timeit df.groupby('year').apply(lambda x: x.sort('prop', ascending=False).iloc[0]['name'])
100 loops, best of 3: 2.14 ms per loop

基准测试是在这个DataFrame上运行的:

In [131]: df
Out[131]: 
   year     name      prop   sex soundex
0  2008        A  0.000027  girl    E450
1  1880     John  0.081541   boy    J500
2  2008        B  0.000027  girl    E450
3  2008  Elianna  0.000127  girl    E450
4  1880  William  0.080511   boy    W450
5  2008        C  0.000027  girl    E450
6  1880        D  0.080511   boy    W450

[7 rows x 5 columns]

答案 1 :(得分:1)

尝试这样的事情:定义一个聚合函数,用prop对每组数据进行排序(为此你必须复制)。该函数返回该复制和排序数据的第一行(即具有最高的prop值)。将此函数传递给.agg并按年份对数据进行分组。

def get_most_popular(x):
    y = x.copy()
    y.sort('prop')
    return y.iloc[0]

df.groupby('year').agg(get_most_popular)

答案 2 :(得分:1)

另一种解决方案:

df.groupby('year').apply(lambda x: x.sort('prop', ascending=False).iloc[0]['name'])

这里发生了什么?

首先,与Woody一样,我们按正确的列分组。 apply()将为该功能提供组级数据。相反,出于理解的目的,我本来可以写

define takeAGroupAndGiveBackMax(group):
    # year level data: first sort it by prop, descending
    group.sort('prop', ascending=False, inplace=True)
    # now return value 'name' of the first entry
    return group.iloc[0]['name']

# the following will give you a data set, indexed on whatever you grouped it by (here: year), and have a columns all the properties you return.    
df.groupby('year').apply(takeAGroupAndGiveBackMax)

为了理解这些,您应该使用该功能。尝试返回多列,多行,您将看到apply()返回给您的内容。它实际上是熊猫带给你的强大工具。