Как передать еще один столбец в качестве аргумента для pandas fillna()
Я хотел бы заполнить пропущенные значения в одном столбце значениями из другого столбца, используя метод fillna
.
(Я читал, что циклически проходить через каждый ряд было бы очень плохой практикой, и что было бы лучше делать все за один раз, но я не мог понять, как это сделать с помощью fillna
.)
Данные до:
Day Cat1 Cat2
1 cat mouse
2 dog elephant
3 cat giraf
4 NaN ant
Данные после:
Day Cat1 Cat2
1 cat mouse
2 dog elephant
3 cat giraf
4 ant ant
Ответы
Ответ 1
Вы можете предоставить этот столбец fillna
(см. docs), он будет использовать эти значения для соответствия индексов для заполнения:
In [17]: df['Cat1'].fillna(df['Cat2'])
Out[17]:
0 cat
1 dog
2 cat
3 ant
Name: Cat1, dtype: object
Ответ 2
Вы могли бы сделать
df.Cat1 = np.where(df.Cat1.isnull(), df.Cat2, df.Cat1)
В общей конструкции на RHS используется тройной шаблон из pandas
cookbook (который он платит, чтобы читать в любом случае). Это векторная версия a? b: c
.
Ответ 3
Просто используйте параметр value
вместо 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
Ответ 4
Вот более общий подход (метод fillna, вероятно, лучше)
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)
Ответ 5
pandas.DataFrame.combine_first также работает.
(Внимание: поскольку "столбцы индекса результата будут объединением соответствующих индексов и столбцов", вы должны проверить соответствие индекса и столбцов.)
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
Сравните с другими ответами:
%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)
Я не использовал этот метод ниже:
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)
потому что это вызовет исключение:
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')
что означает, что np.isnan можно применить к массивам NumPy собственного типа dtype (например, np.float64), но при применении к массивам объектов возникает TypeError.
Поэтому я пересматриваю метод:
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)
Ответ 6
update
Вы можете обновить отсутствующие значения на месте, используя метод update
df.Cat1.update(df.Cat2)
df
Day Cat1 Cat2
0 1 mouse mouse
1 2 elephant elephant
2 3 giraf giraf
3 4 ant ant