如何应用函数创建虚拟变量?

时间:2018-04-30 02:25:29

标签: python python-3.x pandas apply pandas-groupby

import numpy as np
import pandas as pd 
import matplotlib.pyplot as plt

data={'state':[1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4],
      'year':[1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3],
      'pop':[11, 22, 0, 33, 44, 32, 45, 66, 34, 12, 32, 0],
      'gdp':[123, 341, 554, 654, 245, 665, 332 ,321, 344, 232, 542, 221]}
frame=pd.DataFrame(data)

def treat(group):
        if group.ix[group.year==3, 'pop']!=0:  
            group['Treated']=1
        else:
            group['Treated']=0    

frame.groupby('state').apply(treat)

我正在尝试根据某些条件创建变量frame['Treated']if ('year'==3) and ('pop'!=0) - 我认为'州'在Treated组中(因此我创建了一个名为' Treated'的变量)。

不幸的是我最终得到了一个错误:

ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().

我的代码出了什么问题?你知道我怎么能解决这个问题吗?

重新编辑 感谢您的回答,我很抱歉没有清楚地描述我的问题。

我试图再次描述我的问题。 对于状态1,pop 3在第3年为0,因此状态1不在处理组中(如下所示,框架[' Treated'] = 0表示每年的状态1) 对于状态2,pop 3在第3年不等于0,因此状态2在处理组中(如下所示,框架[' Treated'] = 1表示每年的状态2) 其他州因类似原因而被处理。 最终结果如下。

    state  year  pop  gdp  Treated
0       1     1   11  123        0
1       1     2   22  341        0
2       1     3    0  554        0
3       2     1   33  654        1
4       2     2   44  245        1
5       2     3   32  665        1
6       3     1   45  332        1
7       3     2   66  321        1
8       3     3   34  344        1
9       4     1   12  232        0
10      4     2   32  542        0
11      4     3    0  221        0

3 个答案:

答案 0 :(得分:4)

此处不需要

groupby,您只需要np.where

frame['Treated']=np.where((frame.year==3)&(frame.pop!=0),1,0)
frame
Out[429]: 
    gdp  pop  state  year  Treated
0   123   11      1     1        0
1   341   22      1     2        0
2   554    0      1     3        1
3   654   33      2     1        0
4   245   44      2     2        0
5   665   32      2     3        1
6   332   45      3     1        0
7   321   66      3     2        0
8   344   34      3     3        1
9   232   12      4     1        0
10  542   32      4     2        0
11  221    0      4     3        1

答案 1 :(得分:0)

np.where的替代方法是将适当的布尔掩码转换为整数类型。

frame['Treated'] = (frame.year.eq(3) & frame['pop'].ne(0)).astype(int)

您当前的代码无效,因为

group.ix[group.year==3, 'pop']!=0

还有一个Pandas系列,你不能在if语句中安全地使用它。在任何情况下,当您使用布尔掩码解决问题时,使用这样的apply是不好的形式。

答案 2 :(得分:0)

使用pandas.DataFrame.assignpandas.DataFrame.eval

frame.assign(Treated=frame.eval('pop != 0 & year == 3') * 1)

    gdp  pop  state  year  Treated
0   123   11      1     1        0
1   341   22      1     2        0
2   554    0      1     3        0
3   654   33      2     1        0
4   245   44      2     2        0
5   665   32      2     3        1
6   332   45      3     1        0
7   321   66      3     2        0
8   344   34      3     3        1
9   232   12      4     1        0
10  542   32      4     2        0
11  221    0      4     3        0

我乘以1来强制整数。它是较短的代码,但不如@miradulo的astype(int)

那么高效