Pandas:将两列传递给expanding_apply函数

时间:2015-08-10 16:07:04

标签: pandas lambda

我有数据框:

import pandas as pd
id = [0,0,0,0,0,1,1,1,1,1]
value = [1,3,2,5,4,4,3,2,1,5]
test = pd.DataFrame(zip(id, value), columns = ['id', 'value'])

我想要一个扩展的应用函数来识别我们是否达到给定id的新最大值。生成的数据框应如下所示:

   id  value  new_max
0   0      1        1    
1   0      3        1    
2   0      2        0    
3   0      5        1    
4   0      4        0    
5   1      4        1    
6   1      3        0    
7   1      2        0    
8   1      1        0    
9   1      5        1

我似乎无法将两列传递给扩展应用函数。

我试过创建一个新列:

test['id_value'] = zip(test['id'], test['value'])

传递元组:

def new_max(x):
    v, w = list(zip(*x)[0]), list(zip(*x)[1])
    last_id = v[-1]
    last_value = w[-1]
    if any(j >= last_value for j in [w[i] for i, k in enumerate(v[0:-1]) if k == last_id]):
        return 0
    else:
        return 1


test['new_max'] = test['id_value'].apply(lambda x: pd.expanding_apply(x, new_max))

但我收到错误:

AttributeError: 'tuple' object has no attribute 'dtype'

任何建议都将不胜感激!

循环通过两列的一个解决方案 (虽然通过传递两列知道如何做到这一点仍然很好)

def new_max2(x):
    if any(j >= x[-1] for j in x[0:-1]):
        return 0
    else:
        return 1

test.groupby('id')['value'].apply(lambda x: pd.expanding_apply(x, new_max2))

2 个答案:

答案 0 :(得分:1)

这解决了问题,而不是传递多列的一般问题:我会使用groupbycummax,然后看看我们是否达到了新值。例如:

grouped = df.groupby("id")["value"]
cummax = grouped.cummax()
cummax_is_new_value = cummax != cummax.groupby(df.id).shift()
df["new_max"] = cummax_is_new_value.astype(int)

给了我

>>> df
    id  value  new_max
0    0      1        1
1    0      3        1
2    0      2        0
3    0      5        1
4    0      4        0
5    1      4        1
6    1      3        0
7    1      2        0
8    1      1        0
9    1      5        1
10   2      1        1
10   2      1        0
10   2      0        0
10   2      1        0
10   3      1        1

最初我只检查该值是否与之前的值相同,但是在[1,0,1]等情况下失败,其中第二个1都等于累积最大值而不是与以前的价值。这样我们就可以始终使用分组的累积值,因此我们实际上只是按组获取新的累积值。

答案 1 :(得分:0)

自从我与apply一起工作已经很长一段时间了,就像几个发布前的最低版本一样,所以我的回忆可能很糟糕,或者事情可能已经改变了。但是,正如我记得的那样,分组数据作为第一个参数自动传递。

将自己的功能传递给apply时的诱惑就是这样做:

def user_func(df, arg1, arg2):
    return whatever_you_like

DF = pd.DataFrame(your_data)

DF.groupby('col1').appy(user_func(arg1, arg2))

但这不是正确的语法。事实上,最后一行的正确语法是

DF.groupby('col1').apply(user_func, arg1, arg2)

expanding_apply是否以我不知道的方式工作,这可能都完全过时,但可能值得一试。