Tengo los siguientes dos marcos de datos:
import pandas as pd df = pd.DataFrame([[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]], index = [0, 0.25, 0.50, 0.75, 1], columns = [0, 0.25, 0.50, 0.75, 1]) df_cross = pd.DataFrame([[0.0, 0.25], [0.0, 0.75], [0.5, 1]], columns = ['indexes_to_keep', 'cols_to_keep']) df .:
0.00 0.25 0.50 0.75 1.00 0.00 0 0 0 0 0 0.25 0 0 0 0 0 0.50 0 0 0 0 0 0.75 0 0 0 0 0 1.00 0 0 0 0 0 df_cross :
indexes_to_keep cols_to_keep 0 0.0 0.25 1 0.0 0.75 2 0.5 1.00 En el df tengo mis datos almacenados, y el df_cross contiene los índices y las columnas en las que quiero mantener los valores. Los valores en df cuyo índice y columnas no coinciden con ninguna fila de df_cross que quiero reemplazar por una cadena (por ejemplo, "NaN").
La salida esperada es:
0.00 0.25 0.50 0.75 1.00 0.00 NaN 0 NaN 0 NaN 0.25 NaN NaN NaN NaN NaN 0.50 NaN NaN NaN NaN 0 0.75 NaN NaN NaN NaN NaN 1.00 NaN NaN NaN NaN NaNGracias por adelantado.
Pandas no admite elementos de configuración con matrices de coordenadas. Necesitarías usar numpy:
# integer locs rows = df.index.get_indexer(df_cross.indexes_to_keep) cols = df.columns.get_indexer(df_cross.cols_to_keep) # where we want to keep the data mask = np.full(df.shape, False) mask[rows, cols] = True df[:] = df.where(mask) Otra forma, con solo Pandas, de crear una mask es:
mask = (df_cross.assign(val=True) .set_index(['indexes_to_keep', 'cols_to_keep']) ['val'].unstack(fill_value=False) )Producción:
0.00 0.25 0.50 0.75 1.00 0.00 NaN 0.0 NaN 0.0 NaN 0.25 NaN NaN NaN NaN NaN 0.50 NaN NaN NaN NaN 0.0 0.75 NaN NaN NaN NaN NaN 1.00 NaN NaN NaN NaN NaNProbemos la tabulación crosstab en df_cross , luego usemos where para enmascarar los valores
s = pd.crosstab(*df_cross.values.T) df.where(s == 1) 0.00 0.25 0.50 0.75 1.00 0.00 NaN 0.0 NaN 0.0 NaN 0.25 NaN NaN NaN NaN NaN 0.50 NaN NaN NaN NaN 0.0 0.75 NaN NaN NaN NaN NaN 1.00 NaN NaN NaN NaN NaN PD: pd.crosstab(*df_cross.values.T) es solo un atajo sintáctico y es efectivamente equivalente a usar pd.crosstab(df.indexes_to_keep, df.cols_to_keep)