División del dataframe en múltiples marcos de datos

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

En el dataframe (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 bash hacer es dividir el dataframe (datos) en marcos de datos más pequeños y adjuntarlos a una lista (lista de datos):

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, ¡la secuencia de comandos parece ejecutarse para siempre!

¿Hay una manera inteligente de hacerlo?

En primer lugar, su enfoque es ineficiente porque el agregado a la lista de forma consecutiva será lento, ya que tiene que boost periódicamente la lista cuando no hay espacio suficiente para la nueva entrada, las comprensiones de la lista son mejores a este respecto a medida que se determina el tamaño Frente y asignado una vez.

Sin embargo, creo que su enfoque es un desperdicio, ya que ya tiene un dataframe, ¿por qué crear uno nuevo para cada uno de estos usuarios?

Ordenaría el dataframe por la columna 'name' , establecería el índice para que fuera este y, si fuera necesario, no eliminaría la columna.

Luego genere una lista de todas las entradas únicas y luego puede realizar una búsqueda utilizando estas entradas y, de manera crucial, si solo consulta los datos, use los criterios de selección para devolver una vista en el dataframe sin incurrir en una copia de datos costosa.

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' 

EDITAR

sort ahora está en desuso, necesita usar sort_values ahora:

 # sort the dataframe df.sort_values(by='name', axis=1, 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' 

¿Puedo preguntar por qué no hacerlo simplemente cortando el dataframe? 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, listo, tienes un diccionario de marcos de datos tal como (creo) los quieres. ¿Necesitas acceder a uno? Solo entra

 DataFrameDict['Joe'] 

Espero que ayude

Puedes convertir groupby objeto groupby en tuples 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 ABC 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 ABC 2 b 4 9 5 3 b 5 4 7, 'e': Name ABC 4 e 5 2 1, 'a': Name ABC 0 a 4 7 1 1 a 5 8 3, 'f': Name ABC 5 f 4 3 0} print (d['a']) Name ABC 0 a 4 7 1 1 a 5 8 3 

Groupby puede ayudarte a:

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

Luego puede trabajar con cada grupo como con un dataframe para cada participante. Y los métodos del objeto DataFrameGroupBy como (apply, transform, aggregate, head, first, last) 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 nombre.

Fácil:

  [v for k, v in df.groupby('name')] 
 In [28]: df = DataFrame(np.random.randn(1000000,10)) In [29]: df Out[29]:  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 forma grupal (y usted podría hacer una aplicación arbitraria en lugar de una sum)

 In [9]: g = df.groupby(lambda x: x/60) In [8]: g.sum() Out[8]:  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) 

La sum está citonizada, 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 

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 claves que has agrupado, apuntando a las particiones correspondientes. La ventaja es que las claves se mantienen y no desaparecen en el índice de la lista.

El método basado en la comprensión de la lista y groupby : el cual almacena todo el dataframe dividido en la variable de la lista y se puede acceder utilizando el índice.

Ejemplo

 ans = [pd.DataFrame(y) for x, y in DF.groupby('column_name', as_index=False)] ans[0] ans[0].column_name 

Tuve un problema similar. Tuve una serie temporal de ventas diarias para 10 tiendas diferentes y 50 artículos diferentes. Necesitaba dividir el dataframe original en 500 marcos de datos (10 almacenes * 50 almacenes) para aplicar modelos de Aprendizaje automático a cada uno de ellos y no podía hacerlo manualmente.

Este es el jefe de la ttwig de datos:

jefe de la trama de datos: df

He creado dos listas; uno para los nombres de los marcos de datos y otro para el par de matriz [item_number, store_number].

  list=[] for i in range(1,len(items)*len(stores)+1): global list list.append('df'+str(i)) list_couple_s_i =[] for item in items: for store in stores: global list_couple_s_i list_couple_s_i.append([item,store]) 

Y una vez que las dos listas estén listas, puede hacer un bucle en ellas para crear los marcos de datos que desee:

  for name, it_st in zip(list,list_couple_s_i): globals()[name] = df.where((df['item']==it_st[0]) & (df['store']==(it_st[1]))) globals()[name].dropna(inplace=True) 

De esta manera he creado 500 marcos de datos.

¡Esperamos que esto sea útil!