【问题标题】:Creating a new column based on if-elif-else condition根据 if-elif-else 条件创建新列
【发布时间】:2014-03-09 06:25:52
【问题描述】:

我有一个 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 个新列然后组合结果)?

【问题讨论】:

  • 你可以定义一个函数并将其传递给apply 并设置axis=1 会起作用,我不确定我能想到一个可以给你想要的操作
  • 您的解决方案意味着创建 3 列并将它们组合成 1 列,或者您有不同的想法?
  • 您一直在说“创建 3 列”,但我不确定您指的是什么。
  • @DSM 已经回答了这个问题,但我的意思是像 df['C']=df.apply(myFunc(row), axis=1) 这样 myFunc 做你想做的事,这不涉及创建“3列”

标签: python pandas conditional


【解决方案1】:

对于这种特殊的关系,您可以使用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

【讨论】:

    【解决方案2】:

    将上面列出的一些方法形式化:

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

    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)) 
    

    【讨论】:

    • 如果我想在函数中传递另一个参数和行怎么办?如果我这样做,它会说行未定义..
    • 你必须使用.apply函数的args参数:pandas.pydata.org/pandas-docs/stable/generated/…
    • 我是一个学习Python的老SAS用户,肯定有学习曲线! :-) 例如,上面的代码可以用 SAS 写成:data df; set df; if A=B then C=0; else if A>B then C=1; else C=-1; run; 非常优雅和简单。
    • 感谢您的回答。但是,我不明白为什么需要axis=1。没有通过axis=1,该行只有第一列。
    • @Zelazny7 能否请您提供一个矢量化版本?
    【解决方案3】:
    df.loc[df['A'] == df['B'], 'C'] = 0
    df.loc[df['A'] > df['B'], 'C'] = 1
    df.loc[df['A'] < df['B'], 'C'] = -1
    

    使用索引很容易解决。第一行代码如下,如果A 列等于B 列,则创建C 列并将其设置为0。

    【讨论】:

      【解决方案4】:

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

      如果年龄大于 50 则我们认为是 old=yes 否则为 False

      第一步:获取年龄大于50的行的索引

      row_indexes=df[df['age']&gt;=50].index

      第2步: 使用 .loc 我们可以为列

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

      分配一个新值

      50岁以下同理

      row_indexes=df[df['age']&lt;50].index

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

      【讨论】:

        【解决方案5】:

        当您有多个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
        

        【讨论】:

          【解决方案6】:

          可以使用mask的方法:

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

          【讨论】:

            猜你喜欢
            • 2020-12-21
            • 2020-06-20
            • 1970-01-01
            • 2017-05-05
            • 1970-01-01
            • 2021-03-07
            • 2020-07-30
            • 1970-01-01
            相关资源
            最近更新 更多