groupby python split pandas dataframe

groupby - group by en python



División de dataframe en múltiples dataframes (7)

Tengo un marco de datos muy grande (alrededor de 1 millón de filas) con datos de un experimento (60 encuestados). Me gustaría dividir el marco de datos en 60 marcos de datos (un marco de datos para cada participante).

En el marco de datos (llamado = datos) hay una variable llamada ''nombre'' que es el código único para cada participante.

He intentado lo siguiente, pero no pasa nada (o no se detiene en una hora). Lo que pretendo hacer es dividir el marco de datos (datos) en marcos de datos más pequeños y anexarlos a una lista (datalist):

import pandas as pd def splitframe(data, name=''name''): n = data[name][0] df = pd.DataFrame(columns=data.columns) datalist = [] for i in range(len(data)): if data[name][i] == n: df = df.append(data.iloc[i]) else: datalist.append(df) df = pd.DataFrame(columns=data.columns) n = data[name][i] df = df.append(data.iloc[i]) return datalist

No recibo un mensaje de error, ¡parece que el script se ejecuta para siempre!

¿Hay alguna forma inteligente de hacerlo?


¿Puedo preguntar por qué no solo hacerlo cortando el marco de datos? Algo como

#create some data with Names column data = pd.DataFrame({''Names'': [''Joe'', ''John'', ''Jasper'', ''Jez''] *4, ''Ob1'' : np.random.rand(16), ''Ob2'' : np.random.rand(16)}) #create unique list of names UniqueNames = data.Names.unique() #create a data frame dictionary to store your data frames DataFrameDict = {elem : pd.DataFrame for elem in UniqueNames} for key in DataFrameDict.keys(): DataFrameDict[key] = data[:][data.Names == key]

Hey presto tienes un diccionario de marcos de datos al igual que (creo) que los quieres. ¿Necesitas acceder a uno? Solo ingresa

DataFrameDict[''Joe'']

Espero que ayude


Además de la respuesta de Gusev Slava, es posible que desee utilizar los grupos de groupby:

{key: df.loc[value] for key, value in df.groupby("name").groups.items()}

Esto generará un diccionario con las teclas que ha agrupado, apuntando a las particiones correspondientes. La ventaja es que las claves se mantienen y no desaparecen en el índice de la lista.


En primer lugar, su enfoque es ineficiente porque la incorporación a la lista por filas será lenta ya que tiene que crecer periódicamente cuando no hay suficiente espacio para la nueva entrada, la lista de comprensiones es mejor a este respecto ya que se determina el tamaño frente y asignado una vez.

Sin embargo, creo que fundamentalmente su enfoque es un poco inútil ya que tiene un marco de datos, entonces, ¿por qué crear uno nuevo para cada uno de estos usuarios?

Ordenaría el marco de datos por columna ''name'' , establecería el índice para que sea esto y, si es necesario, no soltaré la columna.

Luego genere una lista de todas las entradas únicas y luego puede realizar una búsqueda usando estas entradas y, lo más importante, si solo consulta los datos, use la selección de crítica para devolver una vista en el marco de datos sin incurrir en costosas copias de datos.

Asi que:

# sort the dataframe df.sort(columns=[''name''], inplace=True) # set the index to be this and don''t drop df.set_index(keys=[''name''], drop=False,inplace=True) # get a list of names names=df[''name''].unique().tolist() # now we can perform a lookup on a ''view'' of the dataframe joe = df.loc[df.name==''joe''] # now you can query all ''joes''


Groupby puede ayudarte a:

grouped = data.groupby([''name''])

Luego puede trabajar con cada grupo como con un marco de datos para cada participante. Y los métodos de objeto DataFrameGroupBy como (aplicar, transformar, agregar, encabezar, primero, último) devuelven un objeto DataFrame.

O puede hacer una lista de grouped y obtener todos los DataFrame por índice:

l_grouped = list(grouped) l_grouped[0][1] - DataFrame para el primer grupo con el primer nombre.


Puede convertir groupby object en groupby y luego dict :

df = pd.DataFrame({''Name'':list(''aabbef''), ''A'':[4,5,4,5,5,4], ''B'':[7,8,9,4,2,3], ''C'':[1,3,5,7,1,0]}, columns = [''Name'',''A'',''B'',''C'']) print (df) Name A B C 0 a 4 7 1 1 a 5 8 3 2 b 4 9 5 3 b 5 4 7 4 e 5 2 1 5 f 4 3 0 d = dict(tuple(df.groupby(''Name''))) print (d) {''b'': Name A B C 2 b 4 9 5 3 b 5 4 7, ''e'': Name A B C 4 e 5 2 1, ''a'': Name A B C 0 a 4 7 1 1 a 5 8 3, ''f'': Name A B C 5 f 4 3 0} print (d[''a'']) Name A B C 0 a 4 7 1 1 a 5 8 3


In [28]: df = DataFrame(np.random.randn(1000000,10)) In [29]: df Out[29]: <class ''pandas.core.frame.DataFrame''> Int64Index: 1000000 entries, 0 to 999999 Data columns (total 10 columns): 0 1000000 non-null values 1 1000000 non-null values 2 1000000 non-null values 3 1000000 non-null values 4 1000000 non-null values 5 1000000 non-null values 6 1000000 non-null values 7 1000000 non-null values 8 1000000 non-null values 9 1000000 non-null values dtypes: float64(10) In [30]: frames = [ df.iloc[i*60:min((i+1)*60,len(df))] for i in xrange(int(len(df)/60.) + 1) ] In [31]: %timeit [ df.iloc[i*60:min((i+1)*60,len(df))] for i in xrange(int(len(df)/60.) + 1) ] 1 loops, best of 3: 849 ms per loop In [32]: len(frames) Out[32]: 16667

Aquí hay una manera groupby (y podría hacer una aplicación arbitraria en lugar de suma)

In [9]: g = df.groupby(lambda x: x/60) In [8]: g.sum() Out[8]: <class ''pandas.core.frame.DataFrame''> Int64Index: 16667 entries, 0 to 16666 Data columns (total 10 columns): 0 16667 non-null values 1 16667 non-null values 2 16667 non-null values 3 16667 non-null values 4 16667 non-null values 5 16667 non-null values 6 16667 non-null values 7 16667 non-null values 8 16667 non-null values 9 16667 non-null values dtypes: float64(10)

Suma es cythonized por eso es tan rápido

In [10]: %timeit g.sum() 10 loops, best of 3: 27.5 ms per loop In [11]: %timeit df.groupby(lambda x: x/60) 1 loops, best of 3: 231 ms per loop


splitted_df = [v for k, v in df.groupby(''name'')]