python - 为什么比较顺序对于这个 apply/lambda 不等式很重要?

标签 python pandas

抱歉,这不是一个好标题。简单的例子:

( Pandas 版本 0.16.1)

df = pd.DataFrame({ 'x':range(1,5), 'y':[1,1,1,9] })

工作正常:

df.apply( lambda x: x > x.mean() )

       x      y
0  False  False
1  False  False
2   True  False
3   True   True

这不应该是一样的吗?

df.apply( lambda x: x.mean() < x )
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-467-6f32d50055ea> in <module>()
----> 1 df.apply( lambda x: x.mean() < x )

C:\Users\ei\AppData\Local\Continuum\Anaconda\lib\site-packages\pandas\core\frame.pyc in apply(self, func, axis, broadcast, raw, reduce, args, **kwds)
   3707                     if reduce is None:
   3708                         reduce = True
-> 3709                     return self._apply_standard(f, axis, reduce=reduce)
   3710             else:
   3711                 return self._apply_broadcast(f, axis)

C:\Users\ei\AppData\Local\Continuum\Anaconda\lib\site-packages\pandas\core\frame.pyc in _apply_standard(self, func, axis, ignore_failures, reduce)
   3797             try:
   3798                 for i, v in enumerate(series_gen):
-> 3799                     results[i] = func(v)
   3800                     keys.append(v.name)
   3801             except Exception as e:

<ipython-input-467-6f32d50055ea> in <lambda>(x)
----> 1 df.apply( lambda x: x.mean() < x )

C:\Users\ei\AppData\Local\Continuum\Anaconda\lib\site-packages\pandas\core\ops.pyc in wrapper(self, other, axis)
    586             return NotImplemented
    587         elif isinstance(other, (np.ndarray, pd.Index)):
--> 588             if len(self) != len(other):
    589                 raise ValueError('Lengths must match to compare')
    590             return self._constructor(na_op(self.values, np.asarray(other)),

TypeError: ('len() of unsized object', u'occurred at index x')

举个反例,这两个都有效:

df.mean() < df

df > df.mean()

最佳答案

编辑

终于找到了这个错误 - Issue 9369

如问题中所述-

left = 0 > s works (e.g. a python scalar). So I think this is being treated as a 0-dim array (its a np.int64) (and not as a scalar when called.) I'll mark as a bug. Feel free to dig in

在比较运算符的左侧使用具有 numpy 数据类型(如 np.int64 或 np.float64 等)的比较运算符时会出现此问题。一个简单的解决方法可能就像@santon 在他的回答中指出的那样,将数字转换为 python 标量,而不是使用 numpy 标量。


旧:

我在 Pandas 0.16.2 中试过。

我在您原来的 df 上做了以下操作-

In [22]: df['z'] = df['x'].mean() < df['x']

In [23]: df
Out[23]:
   x  y      z
0  1  1  False
1  2  1  False
2  3  1   True
3  4  9   True

In [27]: df['z'].mean() < df['z']
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-27-afc8a7b869b4> in <module>()
----> 1 df['z'].mean() < df['z']

C:\Anaconda3\lib\site-packages\pandas\core\ops.py in wrapper(self, other, axis)
    586             return NotImplemented
    587         elif isinstance(other, (np.ndarray, pd.Index)):
--> 588             if len(self) != len(other):
    589                 raise ValueError('Lengths must match to compare')
    590             return self._constructor(na_op(self.values, np.asarray(other)),

TypeError: len() of unsized object

对我来说似乎是个错误,我可以将 bool 值与 int 进行比较,反之亦然,但只有在将 bool 值与 bool 值一起使用时才会出现问题(尽管我认为将 mean() 用于 bool 值没有意义)-

In [24]: df['z'] < df['x']
Out[24]:
0    True
1    True
2    True
3    True
dtype: bool

In [25]: df['z'] < df['x'].mean()
Out[25]:
0    True
1    True
2    True
3    True
Name: z, dtype: bool

In [26]: df['x'].mean() < df['z']
Out[26]:
0    False
1    False
2    False
3    False
Name: z, dtype: bool

我尝试并在 Pandas 0.16.1 中重现了这个问题,它也可以使用 - 重现

In [10]: df['x'].mean() < df['x']
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-10-4e5dab1545af> in <module>()
----> 1 df['x'].mean() < df['x']

/opt/anaconda/envs/np18py27-1.9/lib/python2.7/site-packages/pandas/core/ops.pyc in wrapper(self, other, axis)
    586             return NotImplemented
    587         elif isinstance(other, (np.ndarray, pd.Index)):
--> 588             if len(self) != len(other):
    589                 raise ValueError('Lengths must match to compare')
    590             return self._constructor(na_op(self.values, np.asarray(other)),

TypeError: len() of unsized object

In [11]: df['x'] < df['x'].mean()
Out[11]: 
0     True
1     True
2    False
3    False
Name: x, dtype: bool

这似乎也是一个错误,已在 Pandas 0.16.2 版中修复(除了将 bool 值与整数混合时)。我建议使用 -

升级你的 pandas 版本
pip install pandas --upgrade

关于python - 为什么比较顺序对于这个 apply/lambda 不等式很重要?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31480885/

相关文章:

python - pygame - 敌人在与地面碰撞时飞出屏幕?

使用 AVERAGEIF 为更大的数据集生成 Python 列

python - Pandas df.to_dict 在值中打印列的名称

python - 从具有可变长度的列表字典创建数据框

python - 计算一列中数字的频率,同时等于另一列中的文本

python - 是否有类似 Python 子进程的调用接受标准输入字符串并返回标准错误、标准输出和返回代码?

python - 如何在 aiohttp 或 Flask 请求中写入全局变量(或单例)

numpy - 跨两个 2D numpy 数组获取相交行

pandas - 如何在 Pandas 中重复 DatetimeIndex

python - 在CMake命令中调用pipenv ModuleNotFoundError