Pandas: contando valores únicos en un dataframe

Tenemos un DataFrame que se ve así:

> df.ix[:2,:10] 0 1 2 3 4 5 6 7 8 9 10 0 NaN NaN NaN NaN 6 5 NaN NaN 4 NaN 5 1 NaN NaN NaN NaN 8 NaN NaN 7 NaN NaN 5 2 NaN NaN NaN NaN NaN 1 NaN NaN NaN NaN NaN 

Simplemente queremos los recuentos de todos los valores únicos en el DataFrame. Una solución simple es:

 df.stack().value_counts() 

Sin embargo: 1. Parece que la stack devuelve una copia, no una vista, lo que en este caso es prohibitivo para la memoria. ¿Es esto correcto? 2. Quiero agrupar el DataFrame por filas y luego obtener los diferentes histogtwigs para cada agrupación. Si ignoramos los problemas de memoria con la stack y la usamos por ahora, ¿cómo se hace la agrupación correctamente?

 d = pd.DataFrame([[nan, 1, nan, 2, 3], [nan, 1, 1, 1, 3], [nan, 1, nan, 2, 3], [nan,2,2,2, 3]]) len(d.stack()) #14 d.stack().groupby(arange(4)) AssertionError: Grouper and axis must be same length 

El DataFrame astackdo tiene un MultiIndex, con una longitud de un número menor que n_rows*n_columns , porque se eliminan los nan s.

 0 1 1 3 2 4 3 1 0 1 1 1 2 1 3 1 4 3 .... 

Esto significa que no sabemos fácilmente cómo construir nuestra agrupación. Sería mucho mejor operar solo en el primer nivel, pero luego estoy atascado en cómo aplicar la agrupación que realmente quiero.

 d.stack().groupby(level=0).groupby(list('aabb')) KeyError: 'a' 

Edición: Una solución, que no utiliza astackmiento:

 f = lambda x: pd.value_counts(x.values.ravel()) d.groupby(list('aabb')).apply(f) a 1 4 3 2 2 1 b 2 4 3 2 1 1 dtype: int64 

Aunque parece torpe. Si hay una opción mejor, me alegra oírla.

Edit: el comentario de Dan reveló que tenía un error tipográfico, aunque corregirlo todavía no nos lleva a la línea de meta.

Creo que estás haciendo una operación de fila / columna por lo que puedes usar apply :

 In [11]: d.apply(pd.Series.value_counts, axis=1).fillna(0) Out[11]: 1 2 3 0 1 1 1 1 4 0 1 2 1 1 1 3 0 4 1 

Nota: hay un método value_counts DataFrame en desarrollo para 0.14 … que lo hará más eficiente y conciso.

Vale la pena señalar que la función pandas value_counts también funciona en una matriz numpy, por lo que puede pasarle los valores del DataFrame (como una vista de matriz 1-d usando np.ravel ):

 In [21]: pd.value_counts(d.values.ravel()) Out[21]: 2 6 1 6 3 4 dtype: int64 

Además, estaba muy cerca de hacer esto correctamente, pero tendría que astackr y desastackr:

 In [22]: d.stack().groupby(level=0).apply(pd.Series.value_counts).unstack().fillna(0) Out[22]: 1 2 3 0 1 1 1 1 4 0 1 2 1 1 1 3 0 4 1 

Este error parece algo autoexplicativo (4! = 16):

 len(d.stack()) #16 d.stack().groupby(arange(4)) AssertionError: Grouper and axis must be same length 

tal vez quisiste pasar

 In [23]: np.repeat(np.arange(4), 4) Out[23]: array([0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3]) 

No hay suficiente representante para comentar, pero la respuesta de Andy:

 pd.value_counts(d.values.ravel()) 

es lo que he usado personalmente, y me parece que es, con mucho, la solución más versátil y fácil de leer. Otra ventaja es que es fácil usar un subconjunto de las columnas:

 pd.value_counts(d[[1,3,4,6,7]].values.ravel()) 

o

 pd.value_counts(d[["col_title1","col_title2"]].values.ravel()) 

¿Hay alguna desventaja en este enfoque o alguna razón en particular por la que quiera usar stack y groupby?