У меня есть 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]]
источник
import scipy.stats
явно, это не включается, когда вы просто делаетеimport scipy
.axis=0
. Приведенный выше код сообщает режим для каждого столбца ввода. Счетчик сообщает нам, сколько раз он видел отчетный режим в каждом из столбцов. Если вам нужен общий режим, вам нужно указатьaxis=None
. Для получения дополнительной информации, пожалуйста, обратитесь к docs.scipy.org/doc/scipy/reference/generated/…Обновить
В
scipy.stats.mode
этого поста функция была значительно оптимизирована и будет рекомендованным методом.Старый ответ
Это сложная проблема, так как не так много возможностей для расчета режима вдоль оси. Решение прямо вперед для 1-D массивов, где
numpy.bincount
это удобно, наряду сnumpy.unique
сreturn_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
РЕДАКТИРОВАТЬ: предоставил больше информации и изменил подход, чтобы он был более эффективным с точки зрения памяти
источник
Расширение этого метода применяется к поиску режима данных, в котором вам может понадобиться индекс фактического массива, чтобы увидеть, как далеко значение находится от центра распределения.
(_, idx, counts) = np.unique(a, return_index=True, return_counts=True) index = idx[np.argmax(counts)] mode = a[index]
Не забудьте отказаться от режима, когда len (np.argmax (counts))> 1, а также для проверки того, действительно ли он является репрезентативным для центрального распределения ваших данных, вы можете проверить, попадает ли он в ваш интервал стандартного отклонения.
источник
Изящное решение, которое использует только
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)
источник
scipy.stats.mode
. Когда есть несколько значений, имеющих наибольшее количество случаев (несколько режимов), будет выдано ожидание. Но этот метод автоматически перейдет в «первый режим».Если вы хотите использовать только 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]
источник
Я думаю, что очень простой способ - использовать класс Counter. Затем вы можете использовать функцию most_common () экземпляра Counter, как указано здесь .
Для одномерных массивов:
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)
Подсчитывает частоту и возвращает defaultdict.sorted(Counter(data).items())
сортирует с помощью клавиш, а не по частоте. Наконец, необходимо отсортировать частоту, используя другую сортировкуkey = lambda x: x[1]
. Обратное указывает Python, что нужно отсортировать частоту от наибольшей к наименьшей.источник
самый простой способ в Python получить режим списка или массива
import statistics print("mode = "+str(statistics.(mode(a)))
это оно
источник