Tengo una matriz 2D que contiene números enteros (tanto positivos como negativos). Cada fila representa los valores a lo largo del tiempo para un sitio espacial en particular, mientras que cada columna representa valores para varios sitios espaciales durante un tiempo determinado.
Entonces, si la matriz es como:
1 3 4 2 2 7
5 2 2 1 4 1
3 3 2 2 1 1
El resultado debe ser
1 3 2 2 2 1
Tenga en cuenta que cuando hay varios valores para el modo, cualquiera (seleccionado al azar) puede establecerse como modo.
Puedo iterar sobre el modo de búsqueda de columnas una a la vez, pero esperaba que numpy tuviera alguna función incorporada para hacer eso. O si hay un truco para encontrarlo de manera eficiente sin hacer bucles.
Respuestas:
Verificar
scipy.stats.mode()
(inspirado en el comentario de @ 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)
Salida:
ModeResult(mode=array([[1, 3, 2, 2, 1, 1]]), count=array([[1, 2, 2, 2, 1, 2]]))
Como puede ver, devuelve tanto el modo como los recuentos. Puede seleccionar los modos directamente a través de
m[0]
:print(m[0])
Salida:
[[1 3 2 2 1 1]]
fuente
import scipy.stats
explícitamente, no se incluye cuando simplemente hace unimport scipy
.axis=0
. El código anterior informa el modo por columna de la entrada. El recuento nos dice cuántas veces ha visto el modo informado en cada una de las columnas. Si desea el modo general, debe especificaraxis=None
. Para obtener más información, consulte docs.scipy.org/doc/scipy/reference/generated/…Actualizar
La
scipy.stats.mode
función se ha optimizado significativamente desde esta publicación y sería el método recomendadoRespuesta antigua
Este es un problema complicado, ya que no hay mucho para calcular el modo a lo largo de un eje. La solución es sencillo para las matrices 1-D, donde
numpy.bincount
es práctico, junto connumpy.unique
con elreturn_counts
arg comoTrue
. La función n-dimensional más común que veo es scipy.stats.mode, aunque es prohibitivamente lenta, especialmente para matrices grandes con muchos valores únicos. Como solución, he desarrollado esta función y la uso mucho: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]
Resultado:
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]))
Algunos puntos de referencia:
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
EDITAR: proporcionó más antecedentes y modificó el enfoque para que sea más eficiente en la memoria
fuente
Ampliando este método , aplicado para encontrar el modo de los datos donde puede necesitar el índice de la matriz real para ver qué tan lejos está el valor del centro de la distribución.
(_, idx, counts) = np.unique(a, return_index=True, return_counts=True) index = idx[np.argmax(counts)] mode = a[index]
Recuerde descartar el modo cuando len (np.argmax (count))> 1, también para validar si es realmente representativo de la distribución central de sus datos, puede verificar si se encuentra dentro de su intervalo de desviación estándar.
fuente
Una solución ordenada que solo usa
numpy
(noscipy
ni laCounter
clase):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)
fuente
scipy.stats.mode
. Cuando hay varios valores que tienen la mayor frecuencia (modos múltiples), arrojará una expectativa. Pero este método tomará automáticamente el "primer modo".Si solo desea usar numpy:
x = [-1, 2, 1, 3, 3] vals,counts = np.unique(x, return_counts=True)
da
(array([-1, 1, 2, 3]), array([1, 1, 1, 2]))
Y extraerlo:
index = np.argmax(counts) return vals[index]
fuente
Creo que una forma muy sencilla sería utilizar la clase Counter. Luego puede usar la función most_common () de la instancia de Counter como se menciona aquí .
Para matrices 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])
Para matrices de varias dimensiones (poca diferencia):
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])
Esta puede ser una implementación eficiente o no, pero es conveniente.
fuente
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)
El
Counter(data)
cuenta la frecuencia y devuelve un diccionario predeterminado.sorted(Counter(data).items())
ordena usando las teclas, no la frecuencia. Finalmente, es necesario ordenar la frecuencia usando otra ordenada conkey = lambda x: x[1]
. Lo contrario le dice a Python que ordene la frecuencia de mayor a menor.fuente
forma más sencilla en Python de obtener el modo de una lista o matriz a
import statistics print("mode = "+str(statistics.(mode(a)))
Eso es
fuente