【问题标题】:Pandas error when using if-else to create new column: The truth value of a Series is ambiguousPandas 使用 if-else 创建新列时出错:Series 的真值不明确
【发布时间】:2018-01-06 01:14:27
【问题描述】:

我正在使用 Pandas,并尝试使用 Python if-else 语句(又称三元条件运算符)创建一个新列,以避免被零除。

例如下面,我想通过划分 A/B 创建一个新列 C。我想使用 if-else 语句来避免除以 0。

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randint(0, 5, size=(100, 2)), columns=list('AB'))
df.head()
#    A  B
# 0  1  3
# 1  1  2
# 2  0  0
# 3  2  1
# 4  4  2

df['C'] = (df.A / df.B) if df.B > 0.0 else 0.0

但是,我从最后一行得到一个错误:

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

我在 StackOverflow 上搜索并找到了有关此错误的其他帖子,但没有一个涉及这种类型的 if-else 语句。一些帖子包括:

Truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all()

The truth value of a Series is ambiguous in dataframe

Error: The truth value of a Series is ambiguous - Python pandas

任何帮助将不胜感激。

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    怎么办

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

    读作:

    如果df.B 是严格正数,则返回df.A/df.B,否则返回0.

    【讨论】:

    • 谢谢。我认为np.where()应该重命名为:np.if_then_else(if, then, else)
    【解决方案2】:

    df.B > 0 产生一个系列,例如:

    0      True  # 4 > 0 => True
    1      True  # 2 > 0 => True
    2      True  # ...
    3      True
    4      True
    5      True
    6      True
    7      True
    8     False  # 0 is not > 0 => False
    9     False  # 0 is not > 0 => False
    ...
    

    返回的多个值会导致歧义(有些为真,而另一些为假)。

    一种解决方案是使用np.where

    sentinel = np.nan  # Or 0 if you must...
    df = df.assign(C=np.where(df['B'] != 0, df['A'] / df['B'], sentinel))
    >>> df
       A  B    C
    0  2  4  0.5
    1  0  2  0.0
    2  1  2  0.5
    3  4  4  1.0
    4  1  1  1.0
    5  4  4  1.0
    6  2  4  0.5
    7  1  2  0.5
    8  4  0  NaN  # NaN is assigned in cases where the value in Column `B` is zero.
    9  1  0  NaN
    ...
    

    【讨论】:

    • 谢谢。我什至不知道np.where() 存在,也不知道这里为什么需要它。
    • 如果你不想只为where导入numpy,你可以使用pandas的@​​987654327@访问器:pd.np.where(...
    • @robroc 需要明确的是,在导入 pandas 时会隐式导入 numpy,因此在内存或性能上没有差异。唯一的区别是别名nppd.np。您可以通过以下方式自行确认:import numpy as npimport pandas as pdid(pd.np) == id(np),结果为True
    【解决方案3】:

    根据上面关于迭代数据框的@vaishnav 提议,这是一个可行的提议:

    for index, row in df.iterrows():
        if row.B > 0:
            df.loc[index, 'C'] = row.A / row.B
        else:
            df.loc[index, 'C'] = 0
    

    输出:

       A  B         C
    0  3  4  0.750000
    1  0  4  0.000000
    2  4  3  1.333333
    3  2  1  2.000000
    4  1  0  0.000000
    5  0  2  0.000000
    

    【讨论】:

      【解决方案4】:
      df['C']=df.A.div(df.B.mask(df.B.lt(0),0)).fillna(0)
      df
      Out[89]: 
         A  B         C
      0  1  3  0.333333
      1  1  2  0.500000
      2  0  0  0.000000
      3  2  1  2.000000
      4  4  2  2.000000
      

      使用应用 lambda

      df['C']=df.apply(lambda x : x['A']/x['B'] if x['B']>0 else 0,1)
      df
      Out[93]: 
         A  B         C
      0  1  3  0.333333
      1  1  2  0.500000
      2  0  0  0.000000
      3  2  1  2.000000
      4  4  2  2.000000
      

      【讨论】:

        【解决方案5】:

        或者你可以只打开一个 for 循环。

        for i,j in df['a'],df['b']:
            if j>0:
                df['c']=i/j
            else:
                df['c']=0.0
        

        【讨论】:

        • 您应该在发布代码之前对其进行测试。这会引发 ValueError: too many values to unpack (expected 2)。在您遍历 df 的方法之后,我将发布一个单独的可读性答案。
        猜你喜欢
        • 2019-12-11
        • 1970-01-01
        • 1970-01-01
        • 2021-07-09
        • 1970-01-01
        • 2020-10-15
        • 2017-03-27
        • 1970-01-01
        • 2023-01-08
        相关资源
        最近更新 更多