기존 값보다 큰 값이 처음으로 나타남
numpy에 1D 배열이 있고 값이 numpy 배열의 값을 초과하는 배치의 위치를 찾고 싶습니다.
예 :
aa = range(-10,10)
aa
값 5
이 초과 되는 위치를 찾으십시오 .
이것은 조금 더 빠르며 더 멋지게 보입니다.
np.argmax(aa>5)
argmax
보기 처음보기 부터 멈추 므로 True
( "최대 값이 여러 번 발생하는 경우 첫 번째 발생에 해당하는 인덱스가 반환됩니다 .") 다른 목록을 저장하지 않습니다.
In [2]: N = 10000
In [3]: aa = np.arange(-N,N)
In [4]: timeit np.argmax(aa>N/2)
100000 loops, best of 3: 52.3 us per loop
In [5]: timeit np.where(aa>N/2)[0][0]
10000 loops, best of 3: 141 us per loop
In [6]: timeit np.nonzero(aa>N/2)[0][0]
10000 loops, best of 3: 142 us per loop
배열의 정렬 된 내용이 주어지면 더 빠른 방법이 있습니다 : searchsorted .
import time
N = 10000
aa = np.arange(-N,N)
%timeit np.searchsorted(aa, N/2)+1
%timeit np.argmax(aa>N/2)
%timeit np.where(aa>N/2)[0][0]
%timeit np.nonzero(aa>N/2)[0][0]
# Output
100000 loops, best of 3: 5.97 µs per loop
10000 loops, best of 3: 46.3 µs per loop
10000 loops, best of 3: 154 µs per loop
10000 loops, best of 3: 154 µs per loop
In [34]: a=np.arange(-10,10)
In [35]: a
Out[35]:
array([-10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2,
3, 4, 5, 6, 7, 8, 9])
In [36]: np.where(a>5)
Out[36]: (array([16, 17, 18, 19]),)
In [37]: np.where(a>5)[0][0]
Out[37]: 16
나는 이것에 관심이있는 제안 된 모든 답변을 perfplot 과 비교했습니다 . (면책 조항 : 저는 perfplot의 저자입니다.)
은 당신을 당신을 통해 찾고있는 배열되는 것을 알고 난 웬지- 이미 정렬 한 다음
numpy.searchsorted(a, alpha)
당신을위한 것입니다. 시간 작동입니다. 즉, 속도는 어레이의 크기에 의존 하지 않습니다 . 당신은 그것보다 빨리 얻을 수 없습니다.
배열에 대해 아무것도 모르면 문제가 없습니다.
numpy.argmax(a > alpha)
이미 정렬 :
분류되지 않은 :
줄거리를 재현하는 코드 :
import numpy
import perfplot
alpha = 0.5
def argmax(data):
return numpy.argmax(data > alpha)
def where(data):
return numpy.where(data > alpha)[0][0]
def nonzero(data):
return numpy.nonzero(data > alpha)[0][0]
def searchsorted(data):
return numpy.searchsorted(data, alpha)
out = perfplot.show(
# setup=numpy.random.rand,
setup=lambda n: numpy.sort(numpy.random.rand(n)),
kernels=[
argmax, where,
nonzero,
searchsorted
],
n_range=[2**k for k in range(2, 20)],
logx=True,
logy=True,
xlabel='len(array)'
)
요소 사이에 단계가있는 배열
(A)의 경우 range
나 다른 선형 적으로 증가 배열 당신은 모두의 배열을 통해 실제로 반복, 프로그래밍 필요를 선택할 수 있습니다.
def first_index_calculate_range_like(val, arr):
if len(arr) == 0:
raise ValueError('no value greater than {}'.format(val))
elif len(arr) == 1:
if arr[0] > val:
return 0
else:
raise ValueError('no value greater than {}'.format(val))
first_value = arr[0]
step = arr[1] - first_value
# For linearly decreasing arrays or constant arrays we only need to check
# the first element, because if that does not satisfy the condition
# no other element will.
if step <= 0:
if first_value > val:
return 0
else:
raise ValueError('no value greater than {}'.format(val))
calculated_position = (val - first_value) / step
if calculated_position < 0:
return 0
elif calculated_position > len(arr) - 1:
raise ValueError('no value greater than {}'.format(val))
return int(calculated_position) + 1
아마 조금 향상시킬 수 있습니다. 몇 가지 배열과 값을 사용하는 것이 아니라는 것을 의미합니다. 특히 플로트를 사용하는 생각하면 ...
>>> import numpy as np
>>> first_index_calculate_range_like(5, np.arange(-10, 10))
16
>>> np.arange(-10, 10)[16] # double check
6
>>> first_index_calculate_range_like(4.8, np.arange(-10, 10))
15
반복없이 위치를 계산할 수있는 가정하면 항상 시간 ( O(1)
)이 될 수도 있고 계산할 수 있습니다. 그러나 배열에서 단계가 필요합니다. 무효화 된 결과가 생성됩니다.
Numba를 사용하는 일반적인 솔루션
보다 일반적인 접근 방식은 numba 함수를 사용하는 것입니다.
@nb.njit
def first_index_numba(val, arr):
for idx in range(len(arr)):
if arr[idx] > val:
return idx
return -1
그것은 모든 배열에서 작동하지만 배열을 반복해야하는 경우에는 다음과 같다 O(n)
.
>>> first_index_numba(4.8, np.arange(-10, 10))
15
>>> first_index_numba(5, np.arange(-10, 10))
16
기준
Nico Schlömer는 이미 몇 가지 벤치 마크를 제공했지만 새로운 솔루션을 포함하고 다른 "값"솔루션을 테스트하는 것이 유용 할 것이라고 생각했습니다.
테스트 설정 :
import numpy as np
import math
import numba as nb
def first_index_using_argmax(val, arr):
return np.argmax(arr > val)
def first_index_using_where(val, arr):
return np.where(arr > val)[0][0]
def first_index_using_nonzero(val, arr):
return np.nonzero(arr > val)[0][0]
def first_index_using_searchsorted(val, arr):
return np.searchsorted(arr, val) + 1
def first_index_using_min(val, arr):
return np.min(np.where(arr > val))
def first_index_calculate_range_like(val, arr):
if len(arr) == 0:
raise ValueError('empty array')
elif len(arr) == 1:
if arr[0] > val:
return 0
else:
raise ValueError('no value greater than {}'.format(val))
first_value = arr[0]
step = arr[1] - first_value
if step <= 0:
if first_value > val:
return 0
else:
raise ValueError('no value greater than {}'.format(val))
calculated_position = (val - first_value) / step
if calculated_position < 0:
return 0
elif calculated_position > len(arr) - 1:
raise ValueError('no value greater than {}'.format(val))
return int(calculated_position) + 1
@nb.njit
def first_index_numba(val, arr):
for idx in range(len(arr)):
if arr[idx] > val:
return idx
return -1
funcs = [
first_index_using_argmax,
first_index_using_min,
first_index_using_nonzero,
first_index_calculate_range_like,
first_index_numba,
first_index_using_searchsorted,
first_index_using_where
]
from simple_benchmark import benchmark, MultiArgument
그리고 다음을 사용하여 생성합니다.
%matplotlib notebook
b.plot()
항목이 시작됩니다.
b = benchmark(
funcs,
{2**i: MultiArgument([0, np.arange(2**i)]) for i in range(2, 20)},
argument_name="array size")
numba 기능은 가장 잘 수행 된 다음 계산 기능과 검색된 기능을 수행합니다. 다른 솔루션은 훨씬 나빠가 처리합니다.
항목이 끝났습니다
b = benchmark(
funcs,
{2**i: MultiArgument([2**i-2, np.arange(2**i)]) for i in range(2, 20)},
argument_name="array size")
작은 배열의 경우 numba 함수가 놀랍도록 빠른 수행 수행 더 큰 배열의 경우 계산 함수 및 검색 정렬 함수보다 성능이 뛰어납니다.
항목이 sqrt (len)에 있습니다.
b = benchmark(
funcs,
{2**i: MultiArgument([np.sqrt(2**i), np.arange(2**i)]) for i in range(2, 20)},
argument_name="array size")
이 더 흥미 롭습니다. 다시 numba와 계산 기능이 훌륭하게 작동하지 않는 경우 작동하지 않는 작동이 트리거됩니다.
조건에 맞는 값이 없을 때의 기능 비교
또 다른 흥미로운 점은 업그레이드를 반환해야하는 값이없는 경우 함수의 작동 방식입니다.
arr = np.ones(100)
value = 2
for func in funcs:
print(func.__name__)
try:
print('-->', func(value, arr))
except Exception as e:
print('-->', e)
이 결과로 :
first_index_using_argmax
--> 0
first_index_using_min
--> zero-size array to reduction operation minimum which has no identity
first_index_using_nonzero
--> index 0 is out of bounds for axis 0 with size 0
first_index_calculate_range_like
--> no value greater than 2
first_index_numba
--> -1
first_index_using_searchsorted
--> 101
first_index_using_where
--> index 0 is out of bounds for axis 0 with size 0
검색 정렬 됨, argmax 및 numba는 잘못된 값을 반환합니다. 그러나 searchsorted
및 numba
배열에, 대한 올바른 인덱스가 아닌 인덱스를 돌려줍니다.
기능은 where
, min
, nonzero
및 calculate
예외를합니다 던져. 그러나 calculate
실제로 도움이되는 [해석] 예외입니다 .
즉, 배열 값이 적절한 경우, 오류가있는 배열 값이 있고 호출을 처리하는 배열 값이 있습니다.
참고 : 계산 및 searchsorted
옵션은 특수 조건에서만 작동합니다. "계산"기능은 단계를 필요로하고 검색 정렬이 정렬 될 배열을 요구합니다. 이는 적절한 상황 따라서에서 유용 할 수 있지만 이 문제에, 대한 일반적인 해결책 은 아닙니다 . 정렬 된 Python 목록을 다루는 경우 Numpys searchsorted를 사용하는 대신 bisect 모듈을 살펴볼 수 있습니다.
나는 제안하고 싶다
np.min(np.append(np.where(aa>5)[0],np.inf))
이는 조건이 결과를 반환하고, 조건이 결과를 반환합니다 (그리고 where
빈 배열을 반환).
나는 함께 갈 것이다
i = np.min(np.where(V >= x))
여기서는 V
(1D 배열) 벡터이고, x
는 값이고 i
결과 인덱스입니다.
참고 URL : https://stackoverflow.com/questions/16243955/numpy-first-occurrence-of-value-greater- 기존 값보다
'IT' 카테고리의 다른 글
현재 머큐리얼 리비전 해시를 인쇄 하시겠습니까? (0) | 2020.07.14 |
---|---|
Maven에서 사용할 JDK 지정 (0) | 2020.07.14 |
Windows CMD에서 재귀 적으로 파일 또는 폴더 삭제 (0) | 2020.07.14 |
Angular2- 라디오 버튼 바인딩 (0) | 2020.07.14 |
포르노 이미지를 프로그래밍 방식으로 감지하는 가장 좋은 방법은 무엇입니까? (0) | 2020.07.14 |