Calcular el valor medio de las filas que tienen el mismo valor de columna en Pandas.
Estoy tratando de combinar tres DataFrames de pandas juntos.
Uno de ellos (llamado major
) tiene una columna category
donde cada fila tiene una etiqueta única:
A B category
0 90 17 cat_A
1 36 81 cat_B
2 90 67 cat_C
Dos dfs más pequeños (llamados minor
) contienen varias filas y tienen sus propios nombres de columna únicos. Cada df tiene una columna “category” donde cada fila tiene un valor que está presente en la columna de categoría del df principal:
Aquí hay un ejemplo de uno de esos dfs menores. La única diferencia entre ambos es que el primer df menor tiene las columnas C
y D
, mientras que el segundo tiene las columnas E
y F
.
Mi objetivo es calcular la media de los valores en los dfs menores en función de la columna de categoría, para que al final tenga los siguientes dfs:
C D
cat_A 89.00 23.00
cat_B 30.00 33.00
cat_C 28.75 59.25
Donde cada columna contiene la media de los valores que están en cada categoría.
Para ello, hice el siguiente código, donde creamos DataFrames vacíos con los valores de columna de los dfs menores y los índices de los diferentes valores de categorías. Luego lleno este dataframe usando un bucle for donde itero sobre cada valor del índice.
copy_dfs = {}
for k, min_df in minor_dfs.items():
# Obtener columnas de df menor
# Obtener índice de la categoría del df principal
col_names = min_df.columns.values
ind_values = major_df.category.values
# Crear un df con columnas e índices y establecer valores en np.nan
copy_df = pd.DataFrame(np.nan, index=ind_values, columns=col_names)
copy_df = copy_df.drop("category", axis=1)
# Para cada categoría en el índice del dataframe
for maj_category in copy_df.index:
# Seleccionar filas en df menor donde la categoría es la misma que la categoría del df principal
minor_rows = min_df[min_df.category == maj_category]
minor_rows = minor_rows.drop("category", axis=1)
# Calcular los valores medios (por columna) de las filas seleccionadas
# Agregar los valores medios en copy_df, donde el índice corresponde a la categoría del df principal
copy_df.loc[maj_category] = minor_rows.mean()
# Almacenar en el diccionario
copy_dfs[k] = copy_df
Sin embargo, creo que este código podría optimizarse utilizando operaciones vectorizadas, especialmente en la parte en la que itero para cada fila. Entonces me preguntaba si había una manera más fácil e inteligente de lograr lo que estoy tratando de hacer.
davy.ai
Sí, de hecho hay una manera más fácil y eficiente de lograr esto utilizando las funciones
merge
ygroupby
en pandas.Primero, podemos combinar el dataframe principal con cada uno de los dataframes menores en la columna compartida
category
utilizando la funciónmerge
. Esto creará dataframes separados donde cada fila es una combinación de una fila del dataframe principal con una fila de uno de los dataframes menores que comparten la mismacategory
.Esto creará dos dataframes combinados (uno para cada dataframe menor) con columnas
category
,C
yD
para el primero ocategory
,E
yF
para el segundo.A continuación, podemos usar la función
groupby
para agrupar los dataframes combinados porcategory
y calcular la media de cada grupo utilizando la funciónmean
.Esto creará dos dataframes de media (uno para cada dataframe menor) donde cada fila representa la media de los valores en cada columna para una
category
específica.Finalmente, podemos combinar ambos dataframes de media utilizando la función
concat
con el parámetrokeys
para crear un dataframe de múltiples índices.Esto creará el dataframe de resultados esperado con columnas
C
,D
,E
yF
y filascat_A
,cat_B
ycat_C
, donde cada valor es la media de los valores en la categoría y columna correspondiente.