熊猫中的矢量化列比较问题

时间:2016-01-10 04:11:05

标签: python pandas

在比较数据框中的列时,我在理解pandas行为方面遇到了一些麻烦。我想要做的是将逻辑操作应用于不同的列,并根据逻辑结果生成一个结果列,其值为True或False。 (逻辑也可能适用于使用.shift()生成的滞后列值,但我不认为这个问题是必要的。)

问题是我理解比较df.A< df.B是矢量化的(因此它非常快)并且应该按元素结果生成元素。这在我分配给一个系列时有效,但是当我尝试将它分配给一个新列时,它会出错。这是一个例子:

df = pd.DataFrame(np.random.randn(10,2),index=(np.arange(10)),columns=['A','B'])
df['C'] = False  # must add column with [] notation rather than .C
a = df.A < df.B
df.C = A
df

这会产生预期的输出:

          A         B      C
0  1.222631  0.568988  False
1 -0.719666  0.733197   True
2 -2.434720 -0.131745   True
3  0.653228  0.428794  False
4  0.862103  0.402158  False
5 -0.256027 -0.819937  False
6 -1.728418  1.463709   True
7 -1.110928 -2.173016  False
8  0.656576 -1.218179  False
9  0.014519 -0.854039  False

所以,继续并尝试不经过分配系列的中间步骤:

df['C'] = False  # not necessary but a reset
if df.A < df.B: df.C = True

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

所以这里的问题是为什么当我第一次浏览该系列时这是否有效,但不能直接分配给该列?我怀疑有更多关于这种行为,我不明白。

让我继续一个相关的例子。我知道np.where()可能比使用if语句更清晰地进行这样的操作,但我仍然遇到一个指向缺乏理解的问题。以下是我认为应该相同的三行:

df['C'] = np.where((df.A < 0 & df.B > df.A), True, False)  #1 Errors
df['C'] = np.where((df.A < 0) and (df.B > df.A), True, False)  #2 Errors
df['C'] = np.where((df.A < 0) & (df.B > df.A), True, False)  #3 Works

#2和#3之间的差异是和vs&amp; ...我怀疑在幕后我有点不太明白。但为什么Ex 1出错?不需要额外的括号,对吗? 条件1&amp;条件2 (条件1)&amp; (条件2)

为什么会产生不同的结果?更重要的是,这在哪里记录?只是尝试扩展自己的学习和理解,并学习如何处理这样的问题。

谢谢!

1 个答案:

答案 0 :(得分:2)

回答你的问题,

  • 为什么df.A&lt; df.B:df.C = True失败了吗?

Ans:我认为这是由“if”引起的。 您可以将“if”视为一个函数,它只接受True / False或具有已知True / False评估的函数(即,如果为1,如果为-1,如果为0,如果为None)。你可以参考https://docs.python.org/2/library/stdtypes.html。基本上python中的所有东西都在扩展对象类。如果该类具有非零 len 的实现,则“if”应该正常工作。您可以尝试以下方法:

>>> x = 1
>>> x.__nonzero__()
True
>>> x = df.C
>>> x.__nonzero__()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Library/Python/2.7/site-packages/pandas/core/generic.py", line 731, in __nonzero__
     .format(self.__class__.__name__))
 ValueError: The truth value of a Series is ambiguous. Use a.empty,      a.bool(), a.item(), a.any() or a.all().

如果您仍想了解更多详情,我会将您推荐给pandas源代码https://github.com/pydata/pandas/blob/master/pandas/core/generic.py

  • 与&amp;?
  • 比较的原因和不起作用

我认为答案是Difference between 'and' (boolean) vs. '&' (bitwise) in python. Why difference in behavior with lists vs numpy arrays?

  • 为什么我们需要括号?

如果您检查错误消息,

>>> df.B>df.A & df.A <0
Traceback (most recent call last):
   File "<stdin>", line 1, in <module>
   File "/Library/Python/2.7/site-packages/pandas/core/ops.py", line 786, in wrapper
    return filler(self._constructor(na_op(self.values, other.values),
   File "/Library/Python/2.7/site-packages/pandas/core/ops.py", line 758, in na_op
    result = lib.vec_binop(x, y, op)
   File "pandas/lib.pyx", line 914, in pandas.lib.vec_binop (pandas/lib.c:16248)
   File "pandas/lib.pyx", line 907, in pandas.lib.vec_binop (pandas/lib.c:16122)
 TypeError: unsupported operand type(s) for &: 'float' and 'bool'

实际上意味着&amp;运算符试图在float和bool之间使用。浮子在哪里,布尔在哪里? bool是df.B&gt; df.A,浮子是df.A.这意味着什么?这意味着&amp;没有运算符优先级(&lt;,&gt;),请检查此https://www.ibiblio.org/swaroopch/byteofpython/read/operator-precedence.html

另一方面,“和”的运算符优先于(&lt;,&gt;),因此有效。

为了进一步深入挖掘,我相信检查源代码将是一个好方法。 希望它能回答你的问题。