所以,假设我有100,000个浮点数组,每个数组包含100个元素。我需要最高的X个值,但是只有它们大于Y.任何不匹配的元素都应该设置为0.在Python中最快的方法是什么?必须保持秩序。大多数元素已经设置为0。
示例变量:
array = [.06, .25, 0, .15, .5, 0, 0, 0.04, 0, 0]
highCountX = 3
lowValY = .1
预期结果:
array = [0, .25, 0, .15, .5, 0, 0, 0, 0, 0]
答案 0 :(得分: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
现在,如果你只需要highCountX最大的元素,你甚至可以“忘记”小元素(而不是将它们设置为0并对它们进行排序),并且只对大元素列表进行排序:
array_np = numpy.asarray(array)
print numpy.sort(array_np[array_np >= lowValY])[-highCountX:]
当然,如果您只需要一些元素,那么对整个数组进行排序可能不是最佳选择。根据您的需要,您可能需要考虑标准的heapq模块。
答案 1 :(得分:19)
from scipy.stats import threshold
thresholded = threshold(array, 0.5)
:)
答案 2 :(得分: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 ]
作为一个额外的好处,如果你需要,matplotlib可视化库可以很好地支持掩码数组。
答案 3 :(得分: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
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]
表达式a[a<value] = 0
可以在没有numpy
的情况下编写,如下所示:
for i, x in enumerate(a):
if x < value:
a[i] = 0
答案 4 :(得分: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]
分段选择大于lowValY
的所有元素:
[x for x in array if x > lowValY]
此数组仅包含大于阈值的元素数。然后,对它进行排序,使最大值在开始处:
sorted(..., reverse=True)
然后列表索引采用顶部highCountX
元素的阈值:
sorted(...)[highCountX-1]
最后,使用另一个列表解析填写原始数组:
[x if x >= topX else 0 for x in array]
有一个边界条件,其中有两个或多个相等的元素(在您的示例中)是第三个最高元素。结果数组将不止一次包含该元素。
还有其他边界条件,例如len(array) < highCountX
。处理这些条件留给执行者。
答案 5 :(得分:2)
设置元素低于某个阈值为零很容易:
array = [ x if x > threshold else 0.0 for x in array ]
(如果需要,偶尔加上abs()。)
然而,N个最高数字的要求有点模糊。如果有例如该怎么办N + 1等于高于阈值的数字?截断哪一个?
您可以先对数组进行排序,然后将阈值设置为第N个元素的值:
threshold = sorted(array, reverse=True)[N]
array = [ x if x >= threshold else 0.0 for x in array ]
注意:此解决方案针对可读性而非性能进行了优化。
答案 6 :(得分:1)
你可以使用map和lambda,它应该足够快。
new_array = map(lambda x: x if x>y else 0, array)
答案 7 :(得分:0)
使用heap。
这适用于O(n*lg(HighCountX))
。
import heapq
heap = []
array = [.06, .25, 0, .15, .5, 0, 0, 0.04, 0, 0]
highCountX = 3
lowValY = .1
for i in range(1,highCountX):
heappush(heap, lowValY)
heappop(heap)
for i in range( 0, len(array) - 1)
if array[i] > heap[0]:
heappush(heap, array[i])
min = heap[0]
array = [x if x >= min else 0 for x in array]
deletemin在堆O(lg(k))
和插入O(lg(k))
或O(1)
中工作,具体取决于您使用的堆类型。
答案 8 :(得分:0)
正如egon所说,使用堆是一个好主意。但是你可以使用heapq.nlargest
函数来减少一些努力:
import heapq
array = [.06, .25, 0, .15, .5, 0, 0, 0.04, 0, 0]
highCountX = 3
lowValY = .1
threshold = max(heapq.nlargest(highCountX, array)[-1], lowValY)
array = [x if x >= threshold else 0 for x in array]