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\'',)
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 creaisnull.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í queisna = 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
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]
timgeb
Sorprendentemente, pasar un dict con listas vacías como valores parece funcionar para Series.fillna
pero 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
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
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
¿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