programing

NumPy 배열에서 가장 빈도가 높은 숫자 찾기

padding 2023. 6. 27. 21:50
반응형

NumPy 배열에서 가장 빈도가 높은 숫자 찾기

다음과 같은 NumPy 배열이 있다고 가정합니다.

a = np.array([1,2,3,1,2,1,1,1,3,2,2,1])

이 배열에서 가장 빈도가 높은 번호를 어떻게 찾을 수 있습니까?

리스트에 부정적이지 않은 모든 의도가 포함되어 있다면, 당신은 numpy를 살펴봐야 합니다.빈 카운트:

http://docs.scipy.org/doc/numpy/reference/generated/numpy.bincount.html

그런 다음 np.argmax를 사용합니다.

a = np.array([1,2,3,1,2,1,1,1,3,2,2,1])
counts = np.bincount(a)
print(np.argmax(counts))

더 복잡한 리스트(음의 숫자 또는 정수가 아닌 값 포함)의 경우에도 유사한 방법으로 사용할 수 있습니다.또는 numpy를 사용하지 않고 python에서 작업하기를 원한다면,collections.Counter이런 종류의 데이터를 처리하는 좋은 방법입니다.

from collections import Counter
a = [1,2,3,1,2,1,1,1,3,2,2,1]
b = Counter(a)
print(b.most_common(1))

사용할 수 있습니다.

values, counts = np.unique(a, return_counts=True)

ind = np.argmax(counts)
print(values[ind])  # prints the most frequent element

ind = np.argpartition(-counts, kth=10)[:10]
print(values[ind])  # prints the 10 most frequent elements

일부 요소가 다른 요소만큼 자주 발생하는 경우 이 코드는 첫 번째 요소만 반환합니다.

SciPy를 사용할 의사가 있는 경우:

>>> from scipy.stats import mode
>>> mode([1,2,3,1,2,1,1,1,3,2,2,1])
(array([ 1.]), array([ 6.]))
>>> most_frequent = mode([1,2,3,1,2,1,1,1,3,2,2,1])[0][0]
>>> most_frequent
1.0

일부 솔루션에 대한 성능(iPython 사용):

>>> # small array
>>> a = [12,3,65,33,12,3,123,888000]
>>> 
>>> import collections
>>> collections.Counter(a).most_common()[0][0]
3
>>> %timeit collections.Counter(a).most_common()[0][0]
100000 loops, best of 3: 11.3 µs per loop
>>> 
>>> import numpy
>>> numpy.bincount(a).argmax()
3
>>> %timeit numpy.bincount(a).argmax()
100 loops, best of 3: 2.84 ms per loop
>>> 
>>> import scipy.stats
>>> scipy.stats.mode(a)[0][0]
3.0
>>> %timeit scipy.stats.mode(a)[0][0]
10000 loops, best of 3: 172 µs per loop
>>> 
>>> from collections import defaultdict
>>> def jjc(l):
...     d = defaultdict(int)
...     for i in a:
...         d[i] += 1
...     return sorted(d.iteritems(), key=lambda x: x[1], reverse=True)[0]
... 
>>> jjc(a)[0]
3
>>> %timeit jjc(a)[0]
100000 loops, best of 3: 5.58 µs per loop
>>> 
>>> max(map(lambda val: (a.count(val), val), set(a)))[1]
12
>>> %timeit max(map(lambda val: (a.count(val), val), set(a)))[1]
100000 loops, best of 3: 4.11 µs per loop
>>> 

문제와 같은 소규모 어레이의 경우 'max'와 'set'이 가장 좋습니다.

@David Sanders에 따르면 어레이 크기를 100,000개의 요소로 늘리면 "max w/set" 알고리즘이 가장 나쁜 반면 "numpy bincount" 방법이 가장 좋습니다.

에서 시작Python 3.4표준 라이브러리에는 가장 일반적인 단일 데이터 포인트를 반환하는 기능이 포함되어 있습니다.

from statistics import mode

mode([1, 2, 3, 1, 2, 1, 1, 1, 3, 2, 2, 1])
# 1

주파수가 동일한 모드가 여러 개인 경우statistics.mode처음 발견된 항목을 반환합니다.


에서 시작Python 3.8함수는 가장 자주 발생하는 값의 목록을 처음 발생한 순서대로 반환합니다.

from statistics import multimode

multimode([1, 2, 3, 1, 2])
# [1, 2]

또한 모듈을 로드하지 않고 가장 빈번한 값(양 또는 음)을 얻고자 하는 경우 다음 코드를 사용할 수 있습니다.

lVals = [1,2,3,1,2,1,1,1,3,2,2,1]
print max(map(lambda val: (lVals.count(val), val), set(lVals)))

위의 대부분의 답변은 유용하지만, 1) 양의 정수가 아닌 값(예: 부동소수 또는 음의 정수 ;-)을 지원하기 위해 필요하고, 2) Python 2.7(어떤 컬렉션)에는 없습니다.카운터 요구) 및 3) 코드에 스파이웨어(또는 numpy)의 종속성을 추가하지 않는 것을 선호합니다. 그렇다면 O(nlogn)(즉, 효율적)인 순수 파이썬 2.6 솔루션은 다음과 같습니다.

from collections import defaultdict

a = [1,2,3,1,2,1,1,1,3,2,2,1]

d = defaultdict(int)
for i in a:
  d[i] += 1
most_frequent = sorted(d.iteritems(), key=lambda x: x[1], reverse=True)[0]

Python 3에서는 다음이 작동합니다.

max(set(a), key=lambda x: a.count(x))

저는 조쉬 아델의 해결책을 좋아합니다.

하지만 딱 한 가지 방법이 있습니다.

np.bincount()솔루션은 숫자에서만 작동합니다.

끈이 있으면,collections.Counter해결책이 효과가 있을 것입니다.

다음은 순수하게 numpy를 사용하여 값에 관계없이 축을 따라 적용할 수 있는 일반적인 솔루션입니다.또한 고유한 값이 많은 경우 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]

방법을 확장하면 값이 분포의 중심에서 얼마나 떨어져 있는지 확인하기 위해 실제 배열의 인덱스가 필요할 수 있는 데이터 모드를 찾는 데 적용됩니다.

(_, idx, counts) = np.unique(a, return_index=True, return_counts=True)
index = idx[np.argmax(counts)]
mode = a[index]

len(np.argmax(counts)) > 1일 때 모드를 삭제해야 합니다.

다음과 같은 방법을 사용할 수 있습니다.

x = np.array([[2, 5, 5, 2], [2, 7, 8, 5], [2, 5, 7, 9]])
u, c = np.unique(x, return_counts=True)
print(u[c == np.amax(c)])

그러면 다음과 같은 답이 나옵니다.array([2, 5])

사용.np.bincount그리고np.argmax메서드는 numpy 배열에서 가장 일반적인 값을 가져올 수 있습니다.어레이가 이미지 어레이인 경우np.ravel또는np.flatten()1차원 배열로 변환 및 배열하는 방법.

저는 최근에 프로젝트를 하고 컬렉션을 사용하고 있습니다.계산대.(그것이 나를 괴롭혔습니다.)

제 생각에는 컬렉션의 카운터 성능이 매우 좋지 않습니다.그냥 수업을 포장하는 딕트()야.

더욱이 cProfile을 사용하여 메서드를 프로파일링하는 경우 '__missing__' 및 '__instancecheck__' 항목이 전체 시간을 낭비하는 것을 볼 수 있습니다.

most_common()을 사용할 때 주의해야 합니다. most_common(x)을 사용하면 힙 정렬이 호출되고 이 역시 느려집니다.

그런데 numpy의 bincount에도 문제가 있습니다. np.bincount([1,2,4000000])를 사용하면 4000000 요소의 배열을 얻을 수 있습니다.

언급URL : https://stackoverflow.com/questions/6252280/find-the-most-frequent-number-in-a-numpy-array

반응형