根据if-elif-else条件创建新列


103

我有一个DataFrame df

    A    B
a   2    2 
b   3    1
c   1    3

我想根据以下条件创建一个新列:

如果行 A == B: 0

如果行A > B: 1

如果行 A < B: -1

因此,鉴于上表,应为:

    A    B    C
a   2    2    0
b   3    1    1
c   1    3   -1 

对于典型的if else情况np.where(df.A > df.B, 1, -1),pandas是否提供一种特殊的语法来一步解决我的问题(无需创建3个新列,然后合并结果)?


您只需要定义一个函数并将其传递给applyset即可axis=1工作,不确定我是否能想到
可以满足

您的解决方案意味着创建3列并将它们合并为1列,或者您有不同的想法吗?
2014年

您一直说“正在创建3列”,但是我不确定您指的是什么。
DSM 2014年

1
@DSM已经回答了这个问题,但我的意思是类似df['C']=df.apply(myFunc(row), axis=1)myFunc在做什么,这并不涉及创建“ 3列”
EdChum 2014年

1
可能有条件
乔治

Answers:


152

要使上面列出的一些方法正式化:

创建一个对数据框的行进行操作的函数,如下所示:

def f(row):
    if row['A'] == row['B']:
        val = 0
    elif row['A'] > row['B']:
        val = 1
    else:
        val = -1
    return val

然后通过axis=1选项将其应用于您的数据框:

In [1]: df['C'] = df.apply(f, axis=1)

In [2]: df
Out[2]:
   A  B  C
a  2  2  0
b  3  1  1
c  1  3 -1

当然,这不是矢量化的,因此在缩放到大量记录时,性能可能会不佳。不过,我认为它更具可读性。特别是来自SAS背景。

编辑

这是向量化版本

df['C'] = np.where(
    df['A'] == df['B'], 0, np.where(
    df['A'] >  df['B'], 1, -1)) 

1
谢谢你,我与熊猫开始,这是非常有益的+1
nutship

4
如果我想将另一个参数与行中的行一起传递怎么办?如果我这样做,它说没有定义行..
普拉香特马诺哈尔

3
您必须使用函数的args参数.applypandas.pydata.org/pandas-docs/stable/generation/…–
Zelazny7

1
我是学习Python的老SAS用户,肯定有一个学习曲线!:-)例如,上面的代码可以用SAS编写为:data df; set df; if A=B then C=0; else if A>B then C=1; else C=-1; run;非常优雅和简单。
RobertF

1
一个明确定义的答案
Sahil Nagpal

54
df.loc[df['A'] == df['B'], 'C'] = 0
df.loc[df['A'] > df['B'], 'C'] = 1
df.loc[df['A'] < df['B'], 'C'] = -1

易于使用索引解决。代码的第一行看起来像这样,如果columnA等于column,B则创建并设置columnC等于0。


17

对于这种特殊的关系,您可以使用np.sign

>>> df["C"] = np.sign(df.A - df.B)
>>> df
   A  B  C
a  2  2  0
b  3  1  1
c  1  3 -1

6

在此处输入图片说明

假设上面是您的原始数据框,您想添加一个新列“旧”

如果年龄大于50岁,则我们认为年龄较大=是,否则为False

步骤1:获取年龄大于50的行的索引

row_indexes=df[df['age']>=50].index

步骤2:使用.loc我们可以为列分配新值

df.loc[row_indexes,'elderly']="yes"

小于50岁的年龄相同

row_indexes=df[df['age']<50].index

df[row_indexes,'elderly']="no"


1

当您有多个if 条件时,numpy.select该走的路是:

In [4102]: import numpy as np
In [4098]: conditions = [df.A.eq(df.B), df.A.gt(df.B), df.A.lt(df.B)]
In [4096]: choices = [0, 1, -1]

In [4100]: df['C'] = np.select(conditions, choices)

In [4101]: df
Out[4101]: 
   A  B  C
a  2  2  0
b  3  1  1
c  1  3 -1
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.