python - barplot - pandas plot
¿Cómo contar la aparición de cierto elemento en un ndarray en Python? (26)
En Python, tengo un ndarray
y
que se imprime como
array([0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1])
Estoy tratando de contar cuántos
0
sy cuántos
1
s hay en esta matriz.
Pero cuando
y.count(0)
o
y.count(1)
, dice
numpy.ndarray
objetonumpy.ndarray
no tienecount
atributos
¿Qué tengo que hacer?
¿Qué hay de usar
numpy.count_nonzero
, algo así como
>>> import numpy as np
>>> y = np.array([1, 2, 2, 2, 2, 0, 2, 3, 3, 3, 0, 0, 2, 2, 0])
>>> np.count_nonzero(y == 1)
1
>>> np.count_nonzero(y == 2)
7
>>> np.count_nonzero(y == 3)
3
¿Qué pasa con
len(y[y==0])
y
len(y[y==1])
?
Aproveche los métodos que ofrece una serie:
MyArray=numpy.array([[6, 1],[4, 5],[0, 7],[5, 1],[2, 5],[1, 2],[3, 2],[0, 2],[2, 5],[5, 1],[3, 0]])
x=numpy.array([5,1]) # the value I want to count (can be iterator, in a list, etc.)
temp = numpy.ascontiguousarray(MyArray).view(numpy.dtype((numpy.void, MyArray.dtype.itemsize * MyArray.shape[1]))) # convert the 2d-array into an array of analyzable patterns
xt=numpy.ascontiguousarray(x).view(numpy.dtype((numpy.void, x.dtype.itemsize * x.shape[0]))) # convert what you search into one analyzable pattern
numpy.sum(temp==xt) # count of the searched pattern in the list of patterns
Como su ndarray contiene solo 0 y 1, puede usar sum () para obtener la ocurrencia de 1s y len () - sum () para obtener la ocurrencia de 0s.
>>> import pandas as pd
>>> y = np.array([0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1])
>>> pd.Series(y).value_counts()
0 8
1 4
dtype: int64
Convierta su matriz
y
a la lista
l
y luego haga
l.count(1)
y
l.count(0)
>>> y = numpy.array([0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1])
>>> l = list(y)
>>> l.count(1)
4
>>> l.count(0)
8
Esto se puede hacer fácilmente en el siguiente método
num_of_ones = sum(array)
num_of_zeros = len(array)-sum(array)
Honestamente, me resulta más fácil convertir a una serie de pandas o un marco de datos:
import pandas as pd
import numpy as np
df = pd.DataFrame({''data'':np.array([0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1])})
print df[''data''].value_counts()
O este lindo one-liner sugerido por Robert Muil:
pd.Series([0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1]).value_counts()
Implica un paso más, pero una solución más flexible que también funcionaría para matrices 2d y filtros más complicados es crear una máscara booleana y luego usar .sum () en la máscara.
>>>d
{0: 8, 1: 4}
Nadie sugirió usar
numpy.bincount(input, minlength)
con
minlength = np.size(input)
, pero parece ser una buena solución, y definitivamente la
más rápida
:
In [1]: choices = np.random.randint(0, 100, 10000)
In [2]: %timeit [ np.sum(choices == k) for k in range(min(choices), max(choices)+1) ]
100 loops, best of 3: 2.67 ms per loop
In [3]: %timeit np.unique(choices, return_counts=True)
1000 loops, best of 3: 388 µs per loop
In [4]: %timeit np.bincount(choices, minlength=np.size(choices))
100000 loops, best of 3: 16.3 µs per loop
¡Esa es una aceleración loca entre
numpy.unique(x, return_counts=True)
y
numpy.bincount(x, minlength=np.max(x))
!
Numpy tiene un módulo para esto. Solo un pequeño truco. Ponga su matriz de entrada como contenedores.
using numpy.count
$ a = [0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1]
$ np.count(a, 1)
La salida son 2 matrices. Uno con los valores en sí, otro con las frecuencias correspondientes.
Otra solución simple podría ser usar numpy.count_nonzero () :
import numpy as np
y = np.array([0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1])
y_nonzero_num = np.count_nonzero(y==1)
y_zero_num = np.count_nonzero(y==0)
y_nonzero_num
4
y_zero_num
8
No dejes que el nombre te confunda, si lo usas con el booleano como en el ejemplo, hará el truco.
Para contar el número de ocurrencias, puede usar
np.unique(array, return_counts=True)
:
In [75]: boo = np.array([0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1])
# use bool value `True` or equivalently `1`
In [77]: uniq, cnts = np.unique(boo, return_counts=1)
In [81]: uniq
Out[81]: array([0, 1]) #unique elements in input array are: 0, 1
In [82]: cnts
Out[82]: array([8, 4]) # 0 occurs 8 times, 1 occurs 4 times
Para entradas genéricas:
{2: [1, 5],
3: [2, 4, 9, 14],
4: [11, 16],
5: [3, 12],
10: [7, 8],
11: [0, 10, 15],
16: [6, 13]}
Producirá un recuento:
np.mean(x)
E índices:
np.sum(x)
np.sum(1-x)
Para su caso, también puede buscar en numpy.bincount
In [56]: a = np.array([0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1])
In [57]: np.bincount(a)
Out[57]: array([8, 4]) #count of zeros is at index 0 : 8
#count of ones is at index 1 : 4
Personalmente,
(y == 0).sum()
:
(y == 0).sum()
y
(y == 1).sum()
P.ej
import numpy as np
y = np.array([0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1])
num_zeros = (y == 0).sum()
num_ones = (y == 1).sum()
Puede usar la comprensión del diccionario para crear una sola línea ordenada. Puede encontrar más información sobre la comprensión del diccionario aquí.
import numpy
MyArray=numpy.array([0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1]) # array we want to search in
x=0 # the value I want to count (can be iterator, in a list, etc.)
numpy.sum(MyArray==0) # sum of a binary list of the occurence of x in MyArray
Esto creará un diccionario con los valores en su ndarray como claves, y los recuentos de los valores como valores para las claves respectivamente.
Esto funcionará siempre que desee contar las ocurrencias de un valor en matrices de este formato.
Si no desea usar numpy o un módulo de colecciones, puede usar un diccionario:
x = np.array([11, 2, 3, 5, 3, 2, 16, 10, 10, 3, 11, 4, 5, 16, 3, 11, 4])
n = {i:len([j for j in np.where(x==i)[0]]) for i in set(x)}
ix = {i:[j for j in np.where(x==i)[0]] for i in set(x)}
resultado:
{2: 2, 3: 4, 4: 2, 5: 2, 10: 2, 11: 3, 16: 2}
Por supuesto, también puede usar una instrucción if / else. Creo que la función de contador hace casi lo mismo, pero esto es más transparente.
Si sabe exactamente qué número está buscando, puede usar lo siguiente;
lst = np.array([1,1,2,3,3,6,6,6,3,2,1])
(lst == 2).sum()
devuelve cuántas veces se produjo 2 en su matriz.
Tienes una matriz especial con solo 1 y 0 aquí. Entonces, un truco es usar
>>>>y = np.array([0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1])
>>>>mask = y == 0
>>>>mask.sum()
8
que le da el porcentaje de 1s en su matriz. Alternativamente, use
d = dict()
a = [0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1]
for item in a:
try:
d[item]+=1
except KeyError:
d[item]=1
le dará el número absoluto de 1 y 0 en su matriz.
Una respuesta general y simple sería:
>>>counts = {int(value): list(y).count(value) for value in set(y)}
>>>print(counts)
{0: 8, 1: 4}
lo que resultaría en este código completo como ejemplo
y = np.array([0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1])
y.tolist().count(1)
Ahora, si MyArray tiene varias dimensiones y desea contar la ocurrencia de una distribución de valores en línea (= patrón de aquí en adelante)
numpy.sum(MyArray==x) # sum of a binary list of the occurence of x (=0 or 1) in MyArray
Yo usaría np.where:
how_many_0 = len(np.where(a==0.)[0])
how_many_1 = len(np.where(a==1.)[0])
y.tolist().count(val)
con val 0 o 1
Dado que una lista de Python tiene un
count
funciones nativas, la conversión a una lista antes de usar esa función es una solución simple.
numpy.histogram(y, bins=y)
Acabo de copiar el comentario de Seppo Enarvi aquí que merece ser una respuesta adecuada
y = np.array([0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1])
Si sabes que son solo
0
y
1
:
np.sum(y)
te da el número de unos.
np.sum(1-y)
da los ceros.
Para una ligera generalidad, si desea contar
0
y no cero (pero posiblemente 2 o 3):
np.count_nonzero(y)
da el número de cero.
Pero si necesita algo más complicado, no creo que numpy proporcione una buena opción de
count
.
En ese caso, vaya a colecciones:
import collections
collections.Counter(y)
> Counter({0: 8, 1: 4})
Esto se comporta como un dictado
collections.Counter(y)[0]
> 8
>>> a = numpy.array([0, 3, 0, 1, 0, 1, 2, 1, 0, 0, 0, 0, 1, 3, 4])
>>> unique, counts = numpy.unique(a, return_counts=True)
>>> dict(zip(unique, counts))
{0: 7, 1: 4, 2: 1, 3: 2, 4: 1}
Manera no numpy :
Utilice
collections.Counter
.
collections.Counter
;
>> import collections, numpy
>>> a = numpy.array([0, 3, 0, 1, 0, 1, 2, 1, 0, 0, 0, 0, 1, 3, 4])
>>> collections.Counter(a)
Counter({0: 7, 1: 4, 3: 2, 2: 1, 4: 1})
using numpy.count $ a = [0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1] $ np.count(a, 1)