문제

따라서 각각 100 개의 요소가있는 100,000 플로트 어레이가 있다고 가정 해 봅시다. 가장 높은 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]
도움이 되었습니까?

해결책

이것은 전형적인 직업입니다 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 기준 치수.

다른 팁

from scipy.stats import threshold
thresholded = threshold(array, 0.5)

:)

Numpy에는 특별한 MaskedArray 클래스가 있습니다. 전제 조건에 따라 요소를 "마스크"할 수 있습니다. 이것은 0을 할당하는 것보다 필요를 더 잘 나타냅니다. Numpy Operations는 적절한 경우 마스크 된 값을 무시합니다 (예 : 평균 값 찾기).

>>> 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 시각화 라이브러리에서 잘 지원됩니다.

Numpy의 가면 배열에 문서

사용 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

가장 간단한 방법은 다음과 같습니다.

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. 이러한 조건을 처리하는 것은 구현 자에게 맡겨집니다.

어떤 임계 값 미만의 요소는 쉽게 설정합니다.

array = [ x if x > threshold else 0.0 for x in array ]

(필요한 경우 가끔 ABS ().)

그러나 가장 높은 숫자의 요구 사항은 약간 모호합니다. 임계 값 위에있는 예를 들어 N+1 동일한 숫자가 있으면 어떻게됩니까? 어느 쪽이 잘라야합니까?

배열을 먼저 정렬 한 다음 임계 값을 NTH 요소의 값으로 설정할 수 있습니다.

threshold = sorted(array, reverse=True)[N]
array = [ x if x >= threshold else 0.0 for x in array ]

참고 :이 솔루션은 성능이 아닌 가독성에 최적화되었습니다.

Map과 Lambda를 사용할 수 있습니다. 충분히 빠릅니다.

new_array = map(lambda x: x if x>y else 0, array)

a 더미.

이것은 제 시간에 작동합니다 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) 사용하는 힙 유형에 따라

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]
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top