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가 이를 위한 내장 기능을 가지고 있기를 바랍니다.또는 반복하지 않고 효율적으로 찾을 수 있는 방법이 있다면,
확인(@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 게시물 기능이 되었으며, 입니다.
구답
축을 따라 모드를 계산할 수 있는 양이 많지 않기 때문에 이것은 까다로운 문제입니다.어레이에 대한 인 솔루션으로, 1-D 어레이에서 사용할 수 .numpy.bincount편하고가, 다게리와 함께합니다.numpy.uniquereturn_counts아르가스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
편집: 더 많은 배경 정보를 제공하고 메모리 효율성을 높이기 위해 접근 방식을 수정했습니다.
numpy만 사용하려는 경우:
x = [-1, 2, 1, 3, 3]
vals,counts = np.unique(x, return_counts=True)
기브즈
(array([-1, 1, 2, 3]), array([1, 1, 1, 2]))
추출합니다.
index = np.argmax(counts)
return vals[index]
사용하기만 하는 깔끔한 솔루션numpy(아닙니다.scipy도 Counter클래스):
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)
배열([1, 3, 2, 2, 1, 1])
이 방법을 확장하면 값이 분포의 중심에서 얼마나 떨어져 있는지 확인하기 위해 실제 배열의 인덱스가 필요할 수 있는 데이터 모드를 찾는 데 적용됩니다.
(_, idx, counts) = np.unique(a, return_index=True, return_counts=True)
index = idx[np.argmax(counts)]
mode = a[index]
len(np.argmax(counts) > 1일 때 모드를 폐기해야 하며, 실제로 데이터의 중앙 분포를 대표하는지 확인하기 위해 모드가 표준 편차 간격 내에 있는지 여부를 확인할 수 있습니다.
Python에서 목록 또는 배열의 모드를 얻는 가장 간단한 방법 a
import statistics
a=[7,4,4,4,4,25,25,6,7,4867,5,6,56,52,32,44,4,4,44,4,44,4]
print(f"{statistics.mode(a)} is the mode (most frequently occurring number)")
바로 그겁니다.
카운터 클래스를 이용하는 것이 아주 간단한 방법일 것 같습니다.그런 다음 여기에 언급된 대로 카운터 인스턴스의 most_common() 함수를 사용할 수 있습니다.
1-D 어레이의 경우:
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])
다차원 배열의 경우(작은 차이):
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])
이는 효율적인 구현일 수도 있고 아닐 수도 있지만 편리합니다.
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)
그Counter(data)빈도를 카운트하고 기본 딕트를 반환합니다.sorted(Counter(data).items())빈도가 아닌 키를 사용하여 정렬합니다. 마막으로같, 과정이렬다된른주사파로 된 다른 것을 사용하여 .key = lambda x: x[1]그 반대는 Python에게 주파수를 가장 큰 것에서 가장 작은 것으로 정렬하라고 말합니다.
int Value로 모드를 찾으려면 Scipy Stats를 사용하여 어레이 모드를 찾는 가장 쉬운 방법이 여기에 있습니다. 하지만 문제는 코드의 출력이 다음과 같다는 것입니다.
ModeResult(mode=array(2), count=array([[1, 2, 2, 2, 1, 2]])) 나는 정수 출력만 원하므로 동일하게 원한다면 이것을 사용하십시오.
import numpy as np
from scipy import stats
numbers = list(map(int, input().split()))
print(int(stats.mode(numbers)[0]))
Python에서 합니다.print(int(stats.mode(numbers)[0]))
numpy만 사용하고 배열의 인덱스를 사용하지 않고 수행하려면 사전과 numpy를 결합한 다음 구현을 사용할 수 있습니다.
x = np.array([1, 1, 2, 3])
val, count = np.unique(x,return_counts=True)
freq = {}
for v, c in zip(val, count):
freq[v] = c
mode = sorted(freq.items(),key =lambda kv :kv[1])[-1] # (1, 2)
print(mode[0]) # prints 1 (most frequent item, mode)
python에서 dict를 사용하여 모드 찾기
def mode(x):
d={}
k=0
v=0
for i in x:
d[i]=d.get(i,0)+1
if d[i]>v:
k=i
v=d[i]
print(d)
return k
print(mode(x))
NumPy는 일부 데이터의 모드를 계산하기 위한 전용 방법을 제공하지 않습니다.이에 대한 한 가지 이유는 NumPy가 숫자 계산에 중점을 두고 있는 반면, 이 모드가 숫자가 아닌 범주형 변수에 종종 사용되기 때문일 수 있습니다.
여기 판다를 이용한 대안이 있습니다.DataFrame.mode().혼합 유형 데이터를 지원합니다. 아래 예제를 참조하십시오.
import pandas as pd
data = [[1, 3, 4, 2, 2, 7],
[5, 2, 2, 1, 4, 1],
[3, 3, 2, 2, 1, 1]])
df = pd.DataFrame(data)
df.mode()
# 0 1 2 3 4 5
# 0 1 3.0 2.0 2.0 1 1.0
# 1 3 NaN NaN NaN 2 NaN
# 2 5 NaN NaN NaN 4 NaN
여기서는 첫 번째 줄에만 관심이 있습니다.이 값을 가져오려면 다음 중 하나를 사용합니다.
modes = df.mode().values[0] # array([1., 3., 2., 2., 1., 1.])
modes = df.mode().iloc[0] # pd.Series(...)
세부사항:
- 기본적으로 판다는 열별 모드를 계산합니다.인수를 전달하여 행별 모드를 계산할 수 있습니다.
axis=1:df.mode(axis=1) - SciPy 1.9 이후로는 SciPy > = 1.11에서는 비반복 데이터에 대한 지원이 더 이상 사용되지 않습니다.scipy.stats.mode()의 문서를 참조하십시오.SciPy는 Pandas 접근법을 사용할 것을 권장합니다.
- 판다는 모드가 여러 개일 경우 모드를 정렬합니다.결과 데이터 프레임의 첫 번째 행만 사용하면 무작위로 하나를 선택하도록 요청한 OPS 질문에서 약간 벗어납니다.물론, 우리는 이것을 고칠 수 있습니다, 아래를 참조하십시오.
- 함수 모드()는 두 개 이상의 모드가 있을 경우 모든 가능한 모드를 생성하고 데이터 프레임에 저장합니다.불행히도 이로 인해 최대 모드 수가 있는 열보다 모드 수가 적은 열에 대한 NaN 값이 생성됩니다.NaN을 수용하기 위해 Pandas는 dtype의 컬럼을 int에서 float로 변환하는데, 이는 제가 보기에 조금 추하다고 생각합니다.이로부터 회복하기 위해서는 원래의 dtype을 강제로 적용해야 합니다.아래 코드는 이 작업을 수행하는 방법을 보여줍니다.
수정 1: typecast int → float에서 복구:
# Works for both np.ndarray, pd.Series
modes.astype(int)
# For a mixed-type DataFrame, one could do the following:
# (Works only for column-wise modes)
[dtype.type(m) for m, dtype in zip(modes, df.dtypes)]
수정 2: 여러 개인 경우 임의로 모드 선택
modes = df.mode().apply(lambda x: np.random.choice(x.dropna()))
예제: 혼합형 데이터
import numpy as np
import pandas as pd
data = {"col1": ["foo", "bar", "baz", "foo", "bar", "foo", "bar", "baz"],
"col2": [10, 0, 0, 10, 10, 10, 0, 10],
"col3": [42., 14., 0.1, 1., 1., 4., 42., 14.],
"col4": [False, False, False, True, True, True, False, True],
"col5": [None, "abc", "abc", None, "def", "def", None, "abc"],
"col6": [1.2, None, 1.2, 2.3, None, 2.3, 1.2, 2.3] }
df = pd.DataFrame(data)
# col1 col2 col3 col4 col5 col6
# 0 foo 10 42.0 False None 1.2
# 1 bar 0 14.0 False abc NaN
# 2 baz 0 0.1 False abc 1.2
# 3 foo 10 1.0 True None 2.3
# 4 bar 10 1.0 True def NaN
# 5 foo 10 4.0 True def 2.3
# 6 bar 0 42.0 False None 1.2
#
# dtype object int64 float64 bool object float64
modes = df.mode()
# col1 col2 col3 col4 col5 col6
# 0 bar 10.0 1.0 False abc 1.2
# 1 foo NaN 14.0 True NaN 2.3
# 2 NaN NaN 42.0 NaN NaN NaN
#
# dtype object float64 float64 object object float64
데이터에서 Nones가 처리되는 방식, 여러 모드가 정렬되는 방식, col2 및 col4의 dtype이 변경되었음을 확인합니다.
마지막으로, 다음과 같이 여러 개가 있는 경우 유형캐스트를 수정하고 임의로 모드를 선택할 수 있습니다.
modes_fixed = modes.apply(lambda x: np.random.choice(x.dropna()))
modes_fixed = [dtype.type(m) for m, dtype in zip(modes_fixed, df.dtypes)]
# ['foo', 10, 14.0, False, 'abc', 2.3]
언급URL : https://stackoverflow.com/questions/16330831/most-efficient-way-to-find-mode-in-numpy-array
'programing' 카테고리의 다른 글
| 두 날짜 사이의 월을 찾는 가장 좋은 방법 (0) | 2023.07.21 |
|---|---|
| Gradle의 Spring Boot에서 Tomcat 종속성 제외 (0) | 2023.07.21 |
| ResponseEntity에서 CREATED 상태(201 HTTP)를 반환하는 방법 (0) | 2023.07.21 |
| 이벤트 기반 설계와 도메인 기반 설계 마이크로서비스의 차이점은 무엇입니까? (0) | 2023.07.21 |
| IntelliJ 2021.2에서 Spring Boot Live Dev Tools를 사용하여 수정 후 클래스를 재구성하고 서버에 변경 사항을 배포하는 방법은 무엇입니까? (0) | 2023.07.21 |