【问题标题】:pandas if else conditions on multiple columns [duplicate]熊猫if else条件多列[重复]
【发布时间】:2019-12-15 23:11:16
【问题描述】:

假设我有以下 df:

import pandas as pd

data_dic = {
    "a": [0,0,1,2],
    "b": [0,3,4,5],
    "c": [6,7,8,9]
}
df = pd.DataFrame(data_dic)

结果:

   a  b  c
0  0  0  6
1  0  3  7
2  1  4  8
3  2  5  9

我需要根据条件从上面的列中将值传递到新列:

if df.a > 0 then value df.a
else if df.b > 0 then value df.b 
else value df.c

现在我尝试:

df['value'] = [x if x > 0 else 'ww' for x in df['a']]

但不知道如何在此输入更多条件。

预期结果:

   a  b  c value
0  0  0  6  6
1  0  3  7  3
2  1  4  8  1
3  2  5  9  2

感谢您的辛勤工作。

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    使用numpy.select:

    df['value'] = np.select([df.a > 0 , df.b > 0], [df.a, df.b], default=df.c)
    print (df)
       a  b  c  value
    0  0  0  6      6
    1  0  3  7      3
    2  1  4  8      1
    3  2  5  9      2
    

    400k 行中矢量化和循环解决方案的区别:

    df = pd.concat([df] * 100000, ignore_index=True)
    
    In [158]: %timeit df['value2'] = np.select([df.a > 0 , df.b > 0], [df.a, df.b], default=df.c)
    9.86 ms ± 611 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
    
    In [159]: %timeit df['value1'] = [x if x > 0 else y if y>0 else z for x,y,z in zip(df['a'],df['b'],df['c'])]
    399 ms ± 52.3 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
    

    【讨论】:

    • 我知道 numpy 的方式会更快,即使在一个小的 df 中也快很多很多
    【解决方案2】:

    你也可以使用列表推导:

    df['value'] = [x if x > 0 else y if y>0 else z for x,y,z in zip(df['a'],df['b'],df['c'])]
    

    【讨论】:

    • 感谢您的出色解决方案
    • 这很直观,但是@jezrael 的答案在性能方面要好得多,所以请接受它。
    【解决方案3】:

    您可以编写一个函数,将行作为参数,测试您想要测试的任何条件,并返回 TrueFalse 结果 - 然后您可以将其用作选择工具。 (尽管重新阅读您的问题,这可能不是您想要的 - 请参阅下面的第 2 部分)

    执行选择

    apply 将此函数添加到您的数据框,并使用返回的一系列 True/False 答案作为索引来从实际数据框本身中选择值。

    例如

    def selector(row):
        if row['a'] > 0 and row['b'] == 3 :
            return True
        elif row['c'] > 2:
            return True
        else:
            return False
    

    您可以构建任何您喜欢的逻辑,只要确保它在您想要匹配时返回 True,而在您不想要匹配时返回 False。

    然后尝试类似

    df.apply(lambda row : selector(row), axis=1)
    

    它会返回一系列真假答案。将其插入您的 df 以仅选择那些为其计算了 True 值的行。

    df[df.apply(lambda row : selector(row), axis=1)]
    

    这应该会给你你想要的。

    第 2 部分 - 执行计算

    如果您想创建一个包含一些计算结果的新列 - 那么这是一个类似的操作,请创建一个执行计算的函数:

    def mycalc(row):
        if row['a'] > 5 :
            return row['a'] + row['b']
        else:
            return 66
    

    只有这一次,apply 将结果分配给一个新的列名:

    df['value'] = df.apply( lambda row : mycalc(row), axis = 1)
    

    这会给你这个结果。

    【讨论】:

      猜你喜欢
      • 2018-09-20
      • 2021-11-19
      • 2020-09-09
      • 1970-01-01
      • 2021-10-01
      • 2017-12-14
      • 1970-01-01
      • 2019-03-27
      • 2019-08-14
      相关资源
      最近更新 更多