numpy 배열에서 모드를 찾는 가장 효율적인 방법
정수 (양수 또는 음수)를 포함하는 2D 배열이 있습니다. 각 행은 특정 공간 사이트에 대한 시간 경과에 따른 값을 나타내는 반면 각 열은 주어진 시간 동안 다양한 공간 사이트에 대한 값을 나타냅니다.
따라서 배열이 다음과 같은 경우 :
1 3 4 2 2 7
5 2 2 1 4 1
3 3 2 2 1 1
결과는
1 3 2 2 2 1
모드에 대한 값이 여러 개인 경우 임의의 값 (무작위 선택)을 모드로 설정할 수 있습니다.
한 번에 하나씩 모드를 찾는 열을 반복 할 수 있지만 numpy에 내장 기능이 있기를 바라고 있습니다. 또는 반복하지 않고 효율적으로 찾을 수있는 트릭이있는 경우.
확인 scipy.stats.mode()
(@ tom10의 의견에서 영감을 얻음) :
import numpy as np
from scipy import stats
a = np.array([[1, 3, 4, 2, 2, 7],
[5, 2, 2, 1, 4, 1],
[3, 3, 2, 2, 1, 1]])
m = stats.mode(a)
print(m)
산출:
ModeResult(mode=array([[1, 3, 2, 2, 1, 1]]), count=array([[1, 2, 2, 2, 1, 2]]))
보시다시피 모드와 카운트를 모두 반환합니다. 다음을 통해 모드를 직접 선택할 수 있습니다 m[0]
.
print(m[0])
산출:
[[1 3 2 2 1 1]]
최신 정보
scipy.stats.mode
기능은 크게이 게시물 이후로 최적화되어 있으며, 권장되는 방법이 될 것입니다
이전 답변
축을 따라 모드를 계산할 것이 많지 않기 때문에 이것은 까다로운 문제입니다. 해결책은 1D 배열의 경우 numpy.bincount
간단 numpy.unique
하며 return_counts
arg as 와 함께 편리합니다 True
. 내가 보는 가장 일반적인 n 차원 함수는 scipy.stats.mode이지만, 특히 고유 한 값이 많은 대형 배열의 경우 엄청나게 느립니다. 해결책으로이 기능을 개발했으며 많이 사용합니다.
import numpy
def mode(ndarray, axis=0):
# Check inputs
ndarray = numpy.asarray(ndarray)
ndim = ndarray.ndim
if ndarray.size == 1:
return (ndarray[0], 1)
elif ndarray.size == 0:
raise Exception('Cannot compute mode on empty array')
try:
axis = range(ndarray.ndim)[axis]
except:
raise Exception('Axis "{}" incompatible with the {}-dimension array'.format(axis, ndim))
# If array is 1-D and numpy version is > 1.9 numpy.unique will suffice
if all([ndim == 1,
int(numpy.__version__.split('.')[0]) >= 1,
int(numpy.__version__.split('.')[1]) >= 9]):
modals, counts = numpy.unique(ndarray, return_counts=True)
index = numpy.argmax(counts)
return modals[index], counts[index]
# Sort array
sort = numpy.sort(ndarray, axis=axis)
# Create array to transpose along the axis and get padding shape
transpose = numpy.roll(numpy.arange(ndim)[::-1], axis)
shape = list(sort.shape)
shape[axis] = 1
# Create a boolean array along strides of unique values
strides = numpy.concatenate([numpy.zeros(shape=shape, dtype='bool'),
numpy.diff(sort, axis=axis) == 0,
numpy.zeros(shape=shape, dtype='bool')],
axis=axis).transpose(transpose).ravel()
# Count the stride lengths
counts = numpy.cumsum(strides)
counts[~strides] = numpy.concatenate([[0], numpy.diff(counts[~strides])])
counts[strides] = 0
# Get shape of padded counts and slice to return to the original shape
shape = numpy.array(sort.shape)
shape[axis] += 1
shape = shape[transpose]
slices = [slice(None)] * ndim
slices[axis] = slice(1, None)
# Reshape and compute final counts
counts = counts.reshape(shape).transpose(transpose)[slices] + 1
# Find maximum counts and return modals/counts
slices = [slice(None, i) for i in sort.shape]
del slices[axis]
index = numpy.ogrid[slices]
index.insert(axis, numpy.argmax(counts, axis=axis))
return sort[index], counts[index]
결과:
In [2]: a = numpy.array([[1, 3, 4, 2, 2, 7],
[5, 2, 2, 1, 4, 1],
[3, 3, 2, 2, 1, 1]])
In [3]: mode(a)
Out[3]: (array([1, 3, 2, 2, 1, 1]), array([1, 2, 2, 2, 1, 2]))
일부 벤치 마크 :
In [4]: import scipy.stats
In [5]: a = numpy.random.randint(1,10,(1000,1000))
In [6]: %timeit scipy.stats.mode(a)
10 loops, best of 3: 41.6 ms per loop
In [7]: %timeit mode(a)
10 loops, best of 3: 46.7 ms per loop
In [8]: a = numpy.random.randint(1,500,(1000,1000))
In [9]: %timeit scipy.stats.mode(a)
1 loops, best of 3: 1.01 s per loop
In [10]: %timeit mode(a)
10 loops, best of 3: 80 ms per loop
In [11]: a = numpy.random.random((200,200))
In [12]: %timeit scipy.stats.mode(a)
1 loops, best of 3: 3.26 s per loop
In [13]: %timeit mode(a)
1000 loops, best of 3: 1.75 ms per loop
편집 : 더 많은 배경 정보를 제공하고 메모리 효율성을 높이기 위해 접근 방식을 수정했습니다.
Expanding on this method, applied to finding the mode of the data where you may need the index of the actual array to see how far away the value is from the center of the distribution.
(_, idx, counts) = np.unique(a, return_index=True, return_counts=True)
index = idx[np.argmax(counts)]
mode = a[index]
Remember to discard the mode when len(np.argmax(counts)) > 1, also to validate if it is actually representative of the central distribution of your data you may check whether it falls inside your standard deviation interval.
I think a very simple way would be to use the Counter class. You can then use the most_common() function of the Counter instance as mentioned here.
For 1-d arrays:
import numpy as np
from collections import Counter
nparr = np.arange(10)
nparr[2] = 6
nparr[3] = 6 #6 is now the mode
mode = Counter(nparr).most_common(1)
# mode will be [(6,3)] to give the count of the most occurring value, so ->
print(mode[0][0])
For multiple dimensional arrays (little difference):
import numpy as np
from collections import Counter
nparr = np.arange(10)
nparr[2] = 6
nparr[3] = 6
nparr = nparr.reshape((10,2,5)) #same thing but we add this to reshape into ndarray
mode = Counter(nparr.flatten()).most_common(1) # just use .flatten() method
# mode will be [(6,3)] to give the count of the most occurring value, so ->
print(mode[0][0])
This may or may not be an efficient implementation, but it is convenient.
A neat solution that only uses numpy
(not scipy
nor the Counter
class):
A = np.array([[1,3,4,2,2,7], [5,2,2,1,4,1], [3,3,2,2,1,1]])
np.apply_along_axis(lambda x: np.bincount(x).argmax(), axis=0, arr=A)
array([1, 3, 2, 2, 1, 1])
from collections import Counter
n = int(input())
data = sorted([int(i) for i in input().split()])
sorted(sorted(Counter(data).items()), key = lambda x: x[1], reverse = True)[0][0]
print(Mean)
The Counter(data)
counts the frequency and returns a defaultdict. sorted(Counter(data).items())
sorts using the keys, not the frequency. Finally, need to sorted the frequency using another sorted with key = lambda x: x[1]
. The reverse tells Python to sort the frequency from the largest to the smallest.
ReferenceURL : https://stackoverflow.com/questions/16330831/most-efficient-way-to-find-mode-in-numpy-array
'development' 카테고리의 다른 글
하위 요소 클릭 이벤트가 상위 클릭 이벤트를 트리거합니다. (0) | 2020.12.29 |
---|---|
프로젝트에 대해 OutputPath 속성이 설정되지 않았습니다. (0) | 2020.12.29 |
WPF TextBlock과 TextBox간에 차이점이 있습니까? (0) | 2020.12.29 |
Angular-Translate를 사용하여 HTML이 포함 된 문자열을 처리하는 방법은 무엇입니까? (0) | 2020.12.29 |
HTTP 프로토콜의 PUT 및 DELETE 및 PHP에서의 사용법 (0) | 2020.12.29 |