¿Existe una manera más rápida de combinar y multiplicar valores de un Dataframe basándose en los valores de índice?
Tengo dos marcos de datos:
uno (multiíndice) de tamaño (1113, 7897) que contiene valores para diferentes países y sectores en columnas y diferentes IDs en la fila, ejemplo:
Marco de datos F_Frame:
AT BE ...
Food Energy Food Energy ...
ID1
ID2
...
En otro marco de datos (CC_LO) tengo valores de factores con los correspondientes países e IDs que me gustaría emparejar con el marco de datos anterior (F_frame), de modo que multiplique los valores en F_frame con los valores de factores en CC_LO si coinciden por país e ID. Si no coinciden, coloco un cero.
El código que tengo hasta ahora parece funcionar, pero se ejecuta muy lentamente. ¿Existe una forma más inteligente de emparejar las tablas basándose en los nombres de índice/cabecera?
(El código recorre en bucle 49 países y multiplica por el mismo factor para cada 163 sectores dentro del país)
LO_impacts = pd.DataFrame(np.zeros((1113,7987)))
for i in range(0, len(F_frame)):
for j in range(0, 49):
for k in range(0, len(CF_LO)):
if (F_frame.index.get_level_values(1)[i] == CF_LO.iloc[k,1] and
F_frame.columns.get_level_values(0)[j163] == CF_LO.iloc[k,2]):
LO_impacts.iloc[i,(j163):((j+1)163)] = F_frame.iloc[i,(j163):((j+1)163)] * CF_LO.iloc[k,4]
else:
LO_impacts.iloc[i,(j163):((j+1)*163)] == 0
davy.ai
Solución propuesta
Existen algunas mejoras que se pueden realizar a tu código actual para que se ejecute más rápido:
get_level_values()
eiloc()
dentro de tus bucles, ya que estas operaciones pueden ser costosas.CC_LO
con cada fila deF_frame
, combina ambos dataframes utilizando las columnas comunesID
yCountry
, y luego realiza los cálculos en el dataframe fusionado.Aquí tienes un ejemplo de cómo implementar estas mejoras:
Este código primero fusiona los dos dataframes utilizando las columnas comunes
Country
eID
. El métodoreset_index()
se utiliza para convertir el índiceID
deF_frame
en una columna regular antes de fusionar. El dataframe resultantemerged_df
tiene la misma cantidad de filas queF_frame
, pero también incluye la columnaFactor
deCC_LO
donde hay coincidencia.A continuación, se crea una máscara booleana para identificar qué filas tienen una coincidencia (es decir,
Factor
no es NaN). El métodofill_na(0)
se utiliza para reemplazar los valores NaN por ceros y luego se llama al métodoto_numpy()
para convertir la serie resultante en un arreglo numpy unidimensional, que puede ser transmitido a lo largo de las columnas deF_frame
.Finalmente, se calcula la multiplicación elemento por elemento entre
merged_df.iloc[:, 2:]
(es decir, todas las columnas exceptoID
yCountry
) y el arreglo numpy de valores de factor, y se asignan valores cero al dataframe resultanteLO_impacts
para las filas donde no hay coincidencia (es decir,mask
es Falso).Este código debería ser mucho más rápido que tu implementación original, especialmente para dataframes grandes.