read - python pandas excel
Cómo pasar otra columna completa como argumento a los pandas fillna() (5)
Me gustaría completar los valores faltantes en una columna con valores de otra columna, usando el método
fillna
.
(Leí que recorrer cada fila sería una práctica muy mala y que sería mejor hacer todo de una vez, pero no pude descubrir cómo hacerlo con
fillna
).
Datos anteriores:
Day Cat1 Cat2
1 cat mouse
2 dog elephant
3 cat giraf
4 NaN ant
Datos después de:
Day Cat1 Cat2
1 cat mouse
2 dog elephant
3 cat giraf
4 ant ant
Aquí hay un enfoque más general (el método fillna es probablemente mejor)
def is_missing(Cat1,Cat2):
if np.isnan(Cat1):
return Cat2
else:
return Cat1
df[''Cat1''] = df.apply(lambda x: is_missing(x[''Cat1''],x[''Cat2'']),axis=1)
Podrías hacerlo
df.Cat1 = np.where(df.Cat1.isnull(), df.Cat2, df.Cat1)
La construcción general en el RHS utiliza
el patrón ternario del libro de cocina de los
pandas
(que vale la pena leer en cualquier caso).
Es una versión vectorial de
a? b: c
a? b: c
.
Puede proporcionar esta columna para
fillna
(ver
docs
), usará esos valores en los índices coincidentes para llenar:
In [17]: df[''Cat1''].fillna(df[''Cat2''])
Out[17]:
0 cat
1 dog
2 cat
3 ant
Name: Cat1, dtype: object
Simplemente use el parámetro de
value
lugar del
method
:
In [20]: df
Out[20]:
Cat1 Cat2 Day
0 cat mouse 1
1 dog elephant 2
2 cat giraf 3
3 NaN ant 4
In [21]: df.Cat1 = df.Cat1.fillna(value=df.Cat2)
In [22]: df
Out[22]:
Cat1 Cat2 Day
0 cat mouse 1
1 dog elephant 2
2 cat giraf 3
3 ant ant 4
pandas.DataFrame.combine_first también funciona.
( Atención: dado que "las columnas de índice de resultados serán la unión de los respectivos índices y columnas", debe verificar que el índice y las columnas coincidan ) .
import numpy as np
import pandas as pd
df = pd.DataFrame([["1","cat","mouse"],
["2","dog","elephant"],
["3","cat","giraf"],
["4",np.nan,"ant"]],columns=["Day","Cat1","Cat2"])
In: df["Cat1"].combine_first(df["Cat2"])
Out:
0 cat
1 dog
2 cat
3 ant
Name: Cat1, dtype: object
Compare con otras respuestas:
%timeit df["Cat1"].combine_first(df["Cat2"])
181 µs ± 11.3 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
%timeit df[''Cat1''].fillna(df[''Cat2''])
253 µs ± 10.3 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit np.where(df.Cat1.isnull(), df.Cat2, df.Cat1)
88.1 µs ± 793 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
No utilicé este método a continuación:
def is_missing(Cat1,Cat2):
if np.isnan(Cat1):
return Cat2
else:
return Cat1
df[''Cat1''] = df.apply(lambda x: is_missing(x[''Cat1''],x[''Cat2'']),axis=1)
porque generará una excepción:
TypeError: ("ufunc ''isnan'' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''''safe''''", ''occurred at index 0'')
lo que significa que np.isnan se puede aplicar a matrices NumPy de dtype nativo (como np.float64), pero aumenta TypeError cuando se aplica a matrices de objetos .
Entonces reviso el método:
def is_missing(Cat1,Cat2):
if pd.isnull(Cat1):
return Cat2
else:
return Cat1
%timeit df.apply(lambda x: is_missing(x[''Cat1''],x[''Cat2'']),axis=1)
701 µs ± 7.38 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)