Подтвердить что ты не робот

Как передать еще один столбец в качестве аргумента для 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
4b9b3361

Ответ 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