将阵列中的低值归零的最快方法?

Dav*_*vid 34 python arrays floating-point max min

所以,假设我有100,000个浮点数组,每个数组包含100个元素.我需要最高的X个值,但是只有它们大于Y.任何不匹配的元素都应该设置为0.在Python中最快的方法是什么?必须保持秩序.大多数元素已经设置为0.

样本变量:

array = [.06, .25, 0, .15, .5, 0, 0, 0.04, 0, 0]
highCountX = 3
lowValY = .1
Run Code Online (Sandbox Code Playgroud)

预期结果:

array = [0, .25, 0, .15, .5, 0, 0, 0, 0, 0]
Run Code Online (Sandbox Code Playgroud)

Eri*_*got 76

这是NumPy的典型工作,对于这些操作非常快:

array_np = numpy.asarray(array)
low_values_flags = array_np < lowValY  # Where values are low
array_np[low_values_flags] = 0  # All low values set to 0
Run Code Online (Sandbox Code Playgroud)

现在,如果你只需要highCountX最大元素,你甚至可以"忘记"小元素(而不是将它们设置为0并对它们进行排序),并且只对大元素列表进行排序:

array_np = numpy.asarray(array)
print numpy.sort(array_np[array_np >= lowValY])[-highCountX:]
Run Code Online (Sandbox Code Playgroud)

当然,如果只需要一些元素,那么对整个数组进行排序可能不是最佳选择.根据您的需要,您可能需要考虑标准的heapq模块.

  • 很好...使用适当的库可以带你到目前为止:-) (5认同)
  • 什么会更快:`array_np [low_values_indices] = 0`或`array_np*= low_values_indices`? (2认同)

omy*_*dio 19

from scipy.stats import threshold
thresholded = threshold(array, 0.5)
Run Code Online (Sandbox Code Playgroud)

:)

  • 从scipy 0.17.1开始不推荐使用,请参阅https://docs.scipy.org/doc/scipy-0.17.1/reference/generated/scipy.stats.threshold.html#scipy.stats.threshold (2认同)

Ale*_*dev 7

在NumPy中有一个特殊的MaskedArray类就是这样做的.您可以根据任何前提条件"屏蔽"元素.这比分配零更能代表您的需求:numpy操作将在适当时忽略屏蔽值(例如,查找平均值).

>>> from numpy import ma
>>> x = ma.array([.06, .25, 0, .15, .5, 0, 0, 0.04, 0, 0])
>>> x1 = ma.masked_inside(0, 0.1) # mask everything in 0..0.1 range
>>> x1
masked_array(data = [-- 0.25 -- 0.15 0.5 -- -- -- -- --],
         mask = [ True False True False False True True True True True],
   fill_value = 1e+20)
>>> print x.filled(0) # Fill with zeroes
[ 0 0.25 0 0.15 0.5 0 0 0 0 0 ]
Run Code Online (Sandbox Code Playgroud)

作为一个附加的好处,如果你需要,matplotlib可视化库中很好地支持了掩码数组.

numpy中蒙面数组的文档


jfs*_*jfs 6

使用numpy:

# assign zero to all elements less than or equal to `lowValY`
a[a<=lowValY] = 0 
# find n-th largest element in the array (where n=highCountX)
x = partial_sort(a, highCountX, reverse=True)[:highCountX][-1]
# 
a[a<x] = 0 #NOTE: it might leave more than highCountX non-zero elements
           # . if there are duplicates
Run Code Online (Sandbox Code Playgroud)

哪里partial_sort可能是:

def partial_sort(a, n, reverse=False):
    #NOTE: in general it should return full list but in your case this will do
    return sorted(a, reverse=reverse)[:n] 
Run Code Online (Sandbox Code Playgroud)

表达式a[a<value] = 0可以不用numpy如下编写:

for i, x in enumerate(a):
    if x < value:
       a[i] = 0
Run Code Online (Sandbox Code Playgroud)


Gre*_*ill 5

最简单的方法是:

topX = sorted([x for x in array if x > lowValY], reverse=True)[highCountX-1]
print [x if x >= topX else 0 for x in array]
Run Code Online (Sandbox Code Playgroud)

在片段中,这将选择大于以下的所有元素lowValY:

[x for x in array if x > lowValY]
Run Code Online (Sandbox Code Playgroud)

此数组仅包含大于阈值的元素数.然后,对它进行排序,使最大值在开始时:

sorted(..., reverse=True)
Run Code Online (Sandbox Code Playgroud)

然后列表索引获取顶部highCountX元素的阈值:

sorted(...)[highCountX-1]
Run Code Online (Sandbox Code Playgroud)

最后,使用另一个列表理解填充原始数组:

[x if x >= topX else 0 for x in array]
Run Code Online (Sandbox Code Playgroud)

存在一个边界条件,其中有两个或多个相等的元素(在您的示例中)是第三个最高元素.生成的数组将多次包含该元素.

还有其他边界条件,例如if len(array) < highCountX.处理这些条件留给实施者.