Tengo el siguiente marco de datos:

import pandas as pd
df = pd.DataFrame({'name':['apple', 'banana', 'apple', 'mandarin', 'kiwi', 'kiwi'], 'val':[1,5,3,4,5,3]})

Quiero crear marcos de datos separados pasando el nombre de la fruta a la siguiente función:

def split_all_fruits(df, fruit):
    return df[df['name'] == fruit]

Entonces puedo crear marcos de datos simplemente llamando a la función:

apple_df = split_all_fruits(df, 'apple')
banana_df = split_all_fruits(df, 'banana')
#and other fruits

Pero me gustaría crear marcos de datos en bucle for sin llamar a funtion cada vez para cada fruta. Pero, ¿es posible crear un bucle que dé como resultado 5 marcos de datos con el nombre del marco de datos de la lista para cada fruta a la vez? Algo como esto:

#name of dfs
name_of_dfs = ['apple_df', 'banana_df', 'mandarin_df', 'kiwi_df']
#fruit names in df
fruit_name = ['apple', 'banana', 'mandarin', 'kiwi']
#loop to create dfs, but i dont know how to assign list of names in name_of_dfs to respective fruit df
for fruit in fruit_name:
    df_final = split_all_fruits(df,fruit)
    print(df_final)
#it prints all dfs together, but not seperate df with name from list

¡Gracias!

1
Sascha 11 oct. 2019 a las 13:00

4 respuestas

La mejor respuesta

Si bien esto podría hacerse con eval() o globals(), un enfoque mucho mejor (más limpio, más fácil de administrar mediante programación) es usar un dict en su lugar, por ejemplo:

dfs = {name: split_all_fruits(df, name) for name in fruit_name}

Para acceder como, por ejemplo:

dfs['apple']

EDITAR

Si REALMENTE desea tener variables con el nombre de apple_df etc., una forma de hacerlo es modificando el diccionario globals(), por ejemplo:

globals().update({name + '_df': split_all_fruits(df, name) for name in fruit_name})

Para acceder como, por ejemplo:

apple_df

¡Pero ten cuidado porque esto se considera una mala práctica!

1
norok2 11 oct. 2019 a las 10:41

Si desea nombres de variables en lugar de claves de diccionario (no es realmente una buena idea, pero esto fue solicitado por el OP), puede usar exec().

#name of dfs
name_of_dfs = ['apple_df', 'banana_df', 'mandarin_df', 'kiwi_df']
fruit_name = ['apple', 'banana', 'mandarin', 'kiwi']

for fruit, df_name in zip(fruit_name, name_of_dfs):
    exec(f'{df_name} = split_all_fruits(df, "{fruit}")')
    print(globals()[df_name])

Ahora puede acceder a la variable directamente:

print(apple_df)

    name  val
0  apple    1
2  apple    3
1
alec_djinn 11 oct. 2019 a las 11:38

Si desea generar un marco de datos para cada fruta, puede utilizar lo siguiente (señalando que el orden será alfabético de acuerdo con los nombres de las frutas):

[d for name, d in df.groupby("name")]

Si necesita una lista en su orden específica:

[df.query("name == '{}'".format(f)) for f in fruit_name]

Si desea poder acceder a ellos por nombre, puede utilizar un diccionario de comprensión y hacer referencia al nombre de la fruta:

grouped = {name: d for name, d in df.groupby("name")}

# e.g. for apple:
apple_df = grouped['apple']

Finalmente, si necesita tener las variables específicas enumeradas y saber que estas deben estar anticipadas:

grouped = {name: d for name, d in df.groupby("name")}

apple_df, banana_df, mandarin_df, kiwi_df = [grouped[fruit] for fruit in fruit_name]
1
metasomite 11 oct. 2019 a las 10:21

Puedes modificar tu último código como se muestra a continuación

name_of_dfs = ['apple_df', 'banana_df', 'mandarin_df', 'kiwi_df']
#fruit names in df
fruit_name = ['apple', 'banana', 'mandarin', 'kiwi']
dfs = {}
#loop to create dfs, but i dont know how to assign list of names in name_of_dfs to respective fruit df
for fruit in fruit_name:
    df_final = split_all_fruits(df,fruit)
    dfs[fruit] = df_final
    print(df_final)

Luego, acceda a cualquier marco de datos utilizando el nombre del fruto.

dfs['apple']
0
Serdar ERİÇ 11 oct. 2019 a las 10:34
58338834