如何根据多个条件在df中创建新列?

时间:2015-07-14 17:20:13

标签: python numpy pandas

我有一个包含3列的df:v1,v2,v3;其中

v1=[a,b,c,a] 
v2=[d,d,f,n] 
v3=[a,k,i,j] 

我喜欢做的是根据第v1~v3列中的条件创建新列。

我可以做单一条件,

df['v1_a']=np.where(df['v1']=='a',1,0)

它提供了一个名为'v1_a'的新列1/0

但是,如果我想基于多个条件创建新列,则不起作用:

df['v2_flag']=np.where(df['v2']=='f' or df['v2']=='h',1,0)

我该如何做到这一点?

3 个答案:

答案 0 :(得分:2)

如果您使用多个条件,则会收到以下ValueError,因为np.where()不接受多个条件:

ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

所以我建议您使用np.logical_or

df['v2_flag']=np.where(np.logical_or(df['v2']=='f',df['v2']=='h'),1,0)

也请参阅以下示例:

>>> a=np.array([2,2,2,5,7,8,1,4,2,3,4,5,6])
>>> np.where(np.logical_or(a==5,a==2),a,0)
array([2, 2, 2, 5, 0, 0, 0, 0, 2, 0, 0, 5, 0])

答案 1 :(得分:2)

在python中andor只能提供单个结果,并且无法覆盖模块的其他用途,例如您要尝试的巨大的逐行比较。

您需要使用符号&(和)和|(或),它们通常用于逐位比较。这些已经被大熊猫重新定位为逐行比较,这实际上是有道理的,因为它类似于逐位比较。这更像是一个幸福的巧合,因为这些主要是因为这些可以被模块覆盖。

由于这些和平等的优先级,你需要在每个术语周围使用括号,否则它会在|之前计算==,这不是你想要的。你可以使用这样的东西:

df['v2_flag']=np.where((df['v2']=='f')|(df['v2']=='h'),1,0)

答案 2 :(得分:0)

df['v2']=='f' or df['v2']=='h'在到达np.where之前引发ValueError or导致Python在布尔上下文中评估df['v2']=='f'df['v2']=='h'。但是Pandas Series和NumPy数组一样,拒绝减少到一个布尔值 - they raise a ValueError instead

要修复代码,可以使用

df['v2_flag'] = np.where( (df['v2']=='f') | (df['v2']=='h'), 1, 0)

|在两个布尔值系列上执行按位或元素。

定义df['v2_flag']的其他方式包括

df['v2_flag'] = ((df['v2']=='f') | (df['v2']=='h')).astype(int)

df['v2_flag'] = df['v2'].isin(['f', 'h']).astype(int)