Colapsar filas de Pandas para eliminar las entradas de NaN

3

Consideremos el siguiente DataFrame

Nombre A B C D
Tomás 10.0 Yaya Yaya Yaya
Tomás Yaya 15.0 Yaya Yaya
Tomás Yaya Yaya 20,0 Yaya
Tomás Yaya Yaya Yaya 25,0
Tomás 30,0 Yaya Yaya Yaya
Tomás Yaya Yaya Yaya 40,0
John 1.0 Yaya Yaya Yaya
John Yaya 2.0 Yaya Yaya
John Yaya Yaya 3,0 Yaya
John Yaya Yaya Yaya 4.0
John 5,0 Yaya Yaya Yaya
John Yaya 6.0 Yaya Yaya
John Yaya Yaya 7.0 Yaya
John Yaya Yaya Yaya 8.0

Quiero contraerlo para limitar la cantidad de NaNvalores en el DataFrame; puede ser secuencial, es decir, combinar las filas vecinas si es posible, pero todo lo que me importa es que los valores de las columnas A-Dcorresponden a los mismos Namedespués del colapso

Mi resultado perfecto sería

Nombre A B C D
Tomás 10.0 15.0 20,0 25,0
Tomás 30,0 Yaya Yaya 40,0
John 1.0 2.0 3,0 4.0
John 5,0 6.0 7.0 8.0

Por lo que tengo entendido, Pandas groupby('Name')no hará el truco, porque dejará una entrada para cada nombre.

Si eso es de alguna ayuda, uso un diccionario para crear el marco de datos. El diccionario tiene este aspecto:

{
    "a": {
        "tom": [10.0, 30.0],
        "john": [1.0, 5.0]
    },
    "b": {
        "tom": [15.0],
        "john": [2.0, 6.0]
    },
    .....
}

Entonces, básicamente, tomo cada número en el diccionario, luego creo una fila solo con este número y luego combino todas las filas.

¿Existe una forma sencilla de contraer el DataFrame resultante o construir un DataFrame más compacto dado un diccionario de este tipo?

2

Puede .groupby+ .transform(donde "mueve" los valores hacia arriba). Luego suelte las filas que contienen todos los NaNvalores:

print(
    df.set_index("Name")
    .groupby(level=0)
    .transform(lambda x: sorted(x, key=lambda k: pd.isna(k)))
    .dropna(axis=0, how="all")
    .reset_index()
)

Huellas dactilares:

   Name     A     B     C     D
0   tom  10.0  15.0  20.0  25.0
1   tom  30.0   NaN   NaN  40.0
2  john   1.0   2.0   3.0   4.0
3  john   5.0   6.0   7.0   8.0
1
  • 1
    ¡Funciona genial! Muchas gracias.
    Gabriel
    24 de mayo a las 21:11