Cómo llenar los valores Nan del marco de datos con una lista vacía [] en pandas?

5 minutos de lectura

Este es mi marco de datos:

          date                          ids
0     2011-04-23  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,...
1     2011-04-24  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,...
2     2011-04-25  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,...
3     2011-04-26  Nan
4     2011-04-27  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,...
5     2011-04-28  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,...

quiero reemplazar Nan con []. ¿Como hacer eso? relleno([]) no funcionó. incluso lo intenté replace(np.nan, []) pero da error:

 TypeError('Invalid "to_replace" type: \'float\'',)

  • ¿Cómo conseguiste las listas? ids ?

    – Anand S. Kumar

    18/10/2015 a las 14:38

  • No se puede asignar una lista vacía, sería df.ix[df['ids'].isnull(), 'ids'] = set() poner trabajo?

    – Cero

    18/10/2015 a las 14:38

  • Tenga en cuenta que una de las razones por las que esto es tan difícil es porque realmente no está destinado a almacenar valores no escalares en celdas de marcos de datos. Puede hacerlo y, a veces, es útil como paso intermedio (existen varios métodos integrados que generar listas como elementos), pero todavía no hay un fuerte apoyo para ello.

    – DSM

    18/10/2015 a las 17:03

  • Curiosamente, me las arreglé para ejecutar un ciclo infinito (alcanzando RecursionError) usando: df.ids.where(df.ids.isnull(), [[]]).

    – PlasmaBinturong

    30 oct 2019 a las 18:10

Mi enfoque es similar al de @hellpanderrr, pero en su lugar prueba la lista en lugar de usar isnan:

df['ids'] = df['ids'].apply(lambda d: d if isinstance(d, list) else [])

Originalmente intenté usar pd.isnull (o pd.notnull) pero, cuando se le da una lista, devuelve la nulidad de cada elemento.

Después de mucho rascarme la cabeza, encontré este método que debería ser el más eficiente (sin bucles, sin aplicar), solo asignándolo a una porción:

isnull = df.ids.isnull()

df.loc[isnull, 'ids'] = [ [[]] * isnull.sum() ]

El truco estaba en construir tu lista de [] del tamaño adecuado (isnull.sum()), y después enciérralo en una lista: el valor que estás asignando es un 2D matriz (1 columna, isnull.sum() filas) que contienen listas vacías como elementos.

  • Esta es la respuesta más eficiente.

    – HaPsantran

    26 de junio de 2019 a las 19:25

  • Tenga en cuenta que [[]] * isnull.sum() no crea isnull.sum() cantidad de listas vacías, está creando exactamente una lista vacía con múltiples referencias.

    – timgeb

    6 de julio de 2020 a las 5:28


  • Por alguna razón eso no funcionó para mí, pero un simple df.loc[isnull, 'ids'] = [[]] Hace el truco. Podría haber cambiado con versiones más nuevas de pandas.

    – Kris

    7 sep 2020 a las 10:55

  • Me gusta mucho esta respuesta debido a que evita lo potencialmente costoso apply, pero aparece el error ‘debe tener las mismas claves de longitud y valor al configurar con un ndarray’. simplemente haciendo [[]] como sugiere @Khris me da el mismo error. Sin embargo, stackoverflow.com/a/61944174/4345899 parece funcionar, así que isna = df[col].isna(); df.loc[isna, [col]] = pd.Series([[]] * isna.sum()).values en pandas==1.2.2

    – bajo_fantasma

    1 de agosto de 2021 a las 13:27


avatar de usuario de ronkov
ronkov

Una solución sencilla sería:

df['ids'].fillna("").apply(list)

Como señaló @timgeb, esto requiere df['ids'] para contener listas o nan solamente.

  • ¡Enfriar! Tenga en cuenta que esto requiere df['ids'] para contener solo listas, además de los valores faltantes (este es el caso en el ejemplo de OP).

    – timgeb

    4 de febrero de 2021 a las 15:41


  • He probado el método @Nick Edgar con el tuyo. El tuyo es casi 2 veces más rápido. Gracias…

    – Memín

    19 sep 2021 a las 11:15

  • Gracias por la solución. ¿Sabes cómo hacerlo para una lista vacía de 4 elementos?

    – Thomas LESIEUR

    9 de mayo a las 17:33

  • @ThomasLESIEUR podría intentar hacer un .replace{"": whatever}) en vez de .apply(list)

    – ronkov

    10 de mayo a las 10:44

Primero puedes usar loc para localizar todas las filas que tienen un nan en el ids columna, y luego recorra estas filas usando at para establecer sus valores en una lista vacía:

for row in df.loc[df.ids.isnull(), 'ids'].index:
    df.at[row, 'ids'] = []

>>> df
        date                                             ids
0 2011-04-23  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
1 2011-04-24  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
2 2011-04-25  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
3 2011-04-26                                              []
4 2011-04-27  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
5 2011-04-28  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]

avatar de usuario de timgeb
timgeb

Sorprendentemente, pasar un dict con listas vacías como valores parece funcionar para Series.fillnapero no DataFrame.fillna – entonces, si desea trabajar en una sola columna, puede usar esto:

>>> df
     A    B    C
0  0.0  2.0  NaN
1  NaN  NaN  5.0
2  NaN  7.0  NaN
>>> df['C'].fillna({i: [] for i in df.index})
0    []
1     5
2    []
Name: C, dtype: object

La solución se puede extender a DataFrames aplicándola a cada columna.

>>> df.apply(lambda s: s.fillna({i: [] for i in df.index}))
    A   B   C
0   0   2  []
1  []  []   5
2  []   7  []

Nota: para Series/DataFrames grandes con pocos valores faltantes, esto podría crear una cantidad irrazonable de listas vacías desechables.

Probado con pandas 1.0.5.

  • Alguien me va a matar por usar esto 🙂 ¡Buen descubrimiento!

    – DannyDannyDanny

    25 mayo 2021 a las 14:40


Avatar de usuario de Allen Qin
allen qin

Otra solución usando numpy:

df.ids = np.where(df.ids.isnull(), pd.Series([[]]*len(df)), df.ids)

O usando combine_first:

df.ids = df.ids.combine_first(pd.Series([[]]*len(df)))

  • Alguien me va a matar por usar esto 🙂 ¡Buen descubrimiento!

    – DannyDannyDanny

    25 mayo 2021 a las 14:40


avatar de usuario de hellpanderr
hellpanderr

Sin asignaciones:

1) Suponiendo que solo tenemos números flotantes y enteros en nuestro marco de datos

import math
df.apply(lambda x:x.apply(lambda x:[] if math.isnan(x) else x))

2) Para cualquier marco de datos

import math
def isnan(x):
    if isinstance(x, (int, long, float, complex)) and math.isnan(x):
        return True

df.apply(lambda x:x.apply(lambda x:[] if isnan(x) else x))

  • considerando que numpy ya está importado como np, la siguiente línea sería adecuada… df.apply(lambda x: x.apply(lambda x: [] si x es np.nan otra cosa x))

    – Cuidado devastador

    4 de diciembre de 2019 a las 10:39

¿Ha sido útil esta solución?