2011-09-28 10 views
9

Estoy intentando submuestras de filas de un DataFrame según una agrupación. Aquí hay un ejemplo. Digamos que yo defino los siguientes datos:Usando pandas, ¿cómo puedo submuestrear un gran cuadro de datos por grupo de manera eficiente?

from pandas import * 
df = DataFrame({'group1' : ["a","b","a","a","b","c","c","c","c", 
          "c","a","a","a","b","b","b","b"], 
       'group2' : [1,2,3,4,1,3,5,6,5,4,1,2,3,4,3,2,1], 
       'value' : ["apple","pear","orange","apple", 
          "banana","durian","lemon","lime", 
          "raspberry","durian","peach","nectarine", 
          "banana","lemon","guava","blackberry","grape"]}) 

Si el grupo I por group1 y group2, entonces el número de filas de cada grupo está aquí:

In [190]: df.groupby(['group1','group2'])['value'].agg({'count':len}) 
Out[190]: 
     count 
a 1 2  
    2 1  
    3 2  
    4 1  
b 1 2  
    2 2  
    3 1  
    4 1  
c 3 1  
    4 1  
    5 2  
    6 1  

(Si hay una manera aún más concisa para compute eso, dígalo por favor.)

Ahora quiero construir un DataFrame que tenga una fila seleccionada al azar de cada grupo. Mi propuesta es hacerlo así:

In [215]: from random import choice 
In [216]: grouped = df.groupby(['group1','group2']) 
In [217]: subsampled = grouped.apply(lambda x: df.reindex(index=[choice(range(len(x)))])) 
In [218]: subsampled.index = range(len(subsampled)) 
In [219]: subsampled 
Out[219]: 
    group1 group2 value 
0 b  2  pear 
1 a  1  apple 
2 b  2  pear 
3 a  1  apple 
4 a  1  apple 
5 a  1  apple 
6 a  1  apple 
7 a  1  apple 
8 a  1  apple 
9 a  1  apple 
10 a  1  apple 
11 a  1  apple 

que funciona. Sin embargo, mis datos reales tienen alrededor de 2,5 millones de filas y 12 columnas. Si hago esto de una manera sucia construyendo mis propias estructuras de datos, puedo completar esta operación en cuestión de segundos. Sin embargo, mi implementación anterior no termina en 30 minutos (y no parece tener memoria limitada). Como nota al margen, cuando traté de implementar esto en R, primero intenté plyr, que tampoco terminó en un período de tiempo razonable; sin embargo, una solución usando data.table finalizó muy rápidamente.

¿Cómo hago para que esto funcione rápidamente con pandas? Quiero amar este paquete, ¡así que por favor ayuda!

Respuesta

8

He probado con aplicar, parece que cuando hay muchos subgrupos, es muy lento. los grupos de atributos de luces agrupadas es un diccionario, se puede indexar elección directamente de ella:

subsampled = df.ix[(choice(x) for x in grouped.groups.itervalues())] 

EDIT: Desde la versión 0.18.1 pandas, itervalues ya no funciona en objetos GroupBy - sólo puede utilizar .values:

subsampled = df.ix[(choice(x) for x in grouped.groups.values())] 
+3

He respondido en la lista de correo de pystatsmodels sobre esto. Se me ocurrió la misma solución que sugirió: siendo el autor del paquete, no sé de una mejor manera =) –

+0

@wesm, estaba a punto de publicar su respuesta aquí también. ¡Gracias a todos! –

Cuestiones relacionadas