【问题标题】:Replace negative values in an numpy array替换 numpy 数组中的负值
【发布时间】:2012-05-07 06:49:27
【问题描述】:

有没有一种简单的方法可以用 0 替换数组中的所有负值?

我对如何使用 NumPy 数组进行了完整的了解。

例如

a = array([1, 2, 3, -4, 5])

我要回去

[1, 2, 3, 0, 5]

a < 0 给出:

[False, False, False, True, False]

这就是我卡住的地方——如何使用这个数组来修改原始数组。

【问题讨论】:

    标签: python numpy


    【解决方案1】:

    试试numpy.clip

    >>> import numpy
    >>> a = numpy.arange(-10, 10)
    >>> a
    array([-10,  -9,  -8,  -7,  -6,  -5,  -4,  -3,  -2,  -1,   0,   1,   2,
             3,   4,   5,   6,   7,   8,   9])
    >>> a.clip(0, 10)
    array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
    

    您只能使用clip(0) 剪辑下半部分。

    >>> a = numpy.array([1, 2, 3, -4, 5])
    >>> a.clip(0)
    array([1, 2, 3, 0, 5])
    

    您只能使用clip(max=n) 剪辑上半部分。 (这比我之前的建议要好得多,它涉及将NaN 传递给第一个参数并使用out 强制类型。):

    >>> a.clip(max=2)
    array([ 1,  2,  2, -4,  2])
    

    另一个有趣的方法是使用where

    >>> numpy.where(a <= 2, a, 2)
    array([ 1,  2,  2, -4,  2])
    

    最后,考虑aix 的回答。对于简单的操作,我更喜欢 clip,因为它是自记录的,但对于更复杂的操作,他的回答更可取。

    【讨论】:

    • a.clip(0) 就足够了,因为 OP 只想替换负值。 a.clip(0, 10) 将排除 10 以上的任何内容。
    • @Hiett - 我刚试过,剪辑会拿一个。首先是假定最小值。
    • 必须是 numpy 的版本问题 - 这是我的输出:(Pdb) np.clip(w,0) *** TypeError: clip() 需要至少 3 个参数(给定 2 个) - 而: (Pdb) np.clip(w,0,1e6) 数组([[ 0. , 0.605]])
    • @Hiett,numpy 的哪个版本?你试过a的剪辑方法吗?内置函数numpy.clip 给了我同样的错误,但方法没有。
    • 是的,如果你这样称呼它,它似乎可以工作,例如p w.clip(0) array([[ 0. , 0.605]]) - 多么奇怪?
    【解决方案2】:

    你已经成功了一半。试试:

    In [4]: a[a < 0] = 0
    
    In [5]: a
    Out[5]: array([1, 2, 3, 0, 5])
    

    【讨论】:

      【解决方案3】:

      这是一种在没有 NumPy 的情况下在 Python 中实现的方法。创建一个返回所需内容的函数并使用列表推导式或map 函数。

      >>> a = [1, 2, 3, -4, 5]
      
      >>> def zero_if_negative(x):
      ...   if x < 0:
      ...     return 0
      ...   return x
      ...
      
      >>> [zero_if_negative(x) for x in a]
      [1, 2, 3, 0, 5]
      
      >>> map(zero_if_negative, a)
      [1, 2, 3, 0, 5]
      

      【讨论】:

      • 已经走上了这条路,但认为必须有一种更简单、更少 matlab 的 python 方法来使用 numpy (因为我使用的是数组而不是列表)。剪辑很完美
      【解决方案4】:

      另一个不使用 numpy 的极简 Python 解决方案:

      [0 if i < 0 else i for i in a]
      

      无需定义任何额外的函数。

      a = [1, 2, 3, -4, -5.23, 6]
      [0 if i < 0 else i for i in a]
      

      产量:

      [1, 2, 3, 0, 0, 6]
      

      【讨论】:

      • 这很好——我想知道将 if 语句放在列表理解中的语法是什么——我把它放在 for 循环之后然后才得到两个值就出错了,例如[0, 0] 用于您的示例列表
      • 当我最初学习列表理解并尝试不同的事情来测试我的理解时,我也做了同样的事情——对我来说,把它放在 for 循环之后似乎也更直观。但是,现在这样做了 :) 将其放在 for 之前将其应用于列表的每个元素,将其放在之后,意味着只有满足条件时它才会进入结果列表。
      • @Hiett 它只是在列表理解中使用三元运算符(C 中的i &lt; 0 ? 0 : i)。放入括号以使其更清晰[(0 if i &lt; 0 else i) for i in a]。将 if 放在后面是使用列表表达式构造的过滤器部分。 [(i) for i in a if i &lt; 0] 只会返回小于零的项目列表。
      • Numpy 功能强大,因为它通过编译的 c 代码进行大量计算,因此速度更快。将此方法与其他方法进行比较,我发现速度因子差异几乎是 10 倍(这比较慢)。因此,虽然直观且易于阅读,但这绝对不适合计算密集型。
      【解决方案5】:

      还有另一种可能性:

      In [2]: a = array([1, 2, 3, -4, 5])
      
      In [3]: where(a<0, 0, a)
      Out[3]: array([1, 2, 3, 0, 5])
      

      【讨论】: