Tengo un marco de datos:
df = pd.DataFrame({'A': [0, 0, 1], 'B': [1, 0, 0]}, index=['x', 'y', 'z']) AB x 0 1 y 0 0 z 1 0Para cada fila, quiero los nombres de todas las columnas con el valor más bajo (editar: por fila), algo así como:
x A y A y B z B # or x [A] y [A, B] z [B] Sé que idxmin() da la primera instancia del valor más bajo:
df.idxmin(axis=1) x A y A z BPero, ¿cuál es una forma eficiente de obtenerlos todos?
Esta pregunta da todas las filas con el valor mínimo en una columna específica, pero eso no es exactamente lo que quiero.
Editar: aquí hay un mejor juguete df para jugar para obtener los nombres de las columnas con el valor mínimo en cada fila:
df2 = pd.DataFrame({'A': [1, 0, 6], 'B': [3, 0, 2]}, index=['x', 'y', 'z']) AB x 1 3 y 0 0 z 6 2Puedes usar groupby + transform('min') :
s = df.stack() s[s.eq(s.groupby(level=0).transform('min'))]Producción:
x A 0 y A 0 B 0 z B 0Formato alternativo:
s = df.stack() (s[s.eq(s.groupby(level=0).transform('min'))] .reset_index() .groupby('level_0')['level_1'].apply(list) )Producción:
level_0 x [A] y [A, B] z [B] Name: level_1, dtype: objectConvierta el df en bool encontrando cada valor mínimo y extraiga columnas que devuelvan True en una lista
s= df==df.min() df['column_min']=s.agg(lambda s: s.index[s].values, axis=1) AB column_min x 0 1 [A] y 0 0 [A, B] z 1 0 [B]Esta es una sola línea, similar a la segunda solución de @mozway pero usa una máscara booleana similar a la de @wwnde:
min_cols = df.eq(df.min(axis=1), axis=0).stack().groupby(level=0).apply(lambda x: x.index.get_level_values(1)[x].tolist())Producción:
x [A] y [A, B] z [B]