Cara melewatkan seluruh kolom lain sebagai argumen ke pandas fillna ()

95

Saya ingin mengisi nilai yang hilang dalam satu kolom dengan nilai dari kolom lain, menggunakan fillnametode.

(Saya membaca bahwa mengulang setiap baris akan menjadi praktik yang sangat buruk dan akan lebih baik untuk melakukan semuanya sekaligus tetapi saya tidak dapat menemukan cara melakukannya fillna.)

Data sebelumnya:

Day  Cat1  Cat2
1    cat   mouse
2    dog   elephant
3    cat   giraf
4    NaN   ant

Data setelah:

Day  Cat1  Cat2
1    cat   mouse
2    dog   elephant
3    cat   giraf
4    ant   ant
xav
sumber

Jawaban:

174

Anda dapat memberikan kolom ini ke fillna(lihat dokumen ), ini akan menggunakan nilai-nilai tersebut pada indeks yang cocok untuk mengisi:

In [17]: df['Cat1'].fillna(df['Cat2'])
Out[17]:
0    cat
1    dog
2    cat
3    ant
Name: Cat1, dtype: object
joris
sumber
7
Bagus! Saya tidak tahu yang fillnamembutuhkan seri.
Ami Tavory
1
Terima kasih! Saya pikir seri tersebut harus berukuran tepat dari jumlah nilai NA.
xav
Ia bekerja juga untuk kerangka data untuk baris multikolumnar. Fitur fillna itu sangat membantu.
Wertikal
19

Anda bisa melakukannya

df.Cat1 = np.where(df.Cat1.isnull(), df.Cat2, df.Cat1)

Konstruksi keseluruhan di kanan atas menggunakan pola terner dari pandasbuku masak (yang bagaimanapun juga bermanfaat untuk dibaca). Ini adalah versi vektor dari a? b: c.

Ami Tavory
sumber
Bukan solusi yang saya gunakan untuk masalah ini tetapi pola yang sangat menarik! Terima kasih!
xav
apakah ada cara untuk menggunakan ini untuk beberapa kolom? misalnya jika df ini memiliki cat1, cat2, cat3, cat4, cat5 dan katakanlah cat5 kosong. akankah ada cara untuk mengisi cat5 dengan nilai dari cat1 jika cat1 kosong lalu cat2, jika cat2 kosong lalu cat3 dll?
pengguna8322222
@ user8322222 Saya pasti terlambat tetapi jika ada yang memiliki pertanyaan ini, Anda dapat melakukan nested np.where, seperti yang akan Anda lakukan di excel cell = np.where (cond, val_true, np.where (cond, val_true, val_false), ).
Kaisar
Anda ingin menyebutkan bahwa ini hanya mendefinisikan ulang panda yang ada di dalamnya pd.DataFrame.fillna(). Dan saya menduga perilaku sudut-kasus mungkin berbeda misalnya untuk panjang seri serasi dari dataframes berbeda: DFA [ 'cat1'], DFB [ 'CAT2']
smci
8

Cukup gunakan valueparameter sebagai ganti 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
chrisaycock
sumber
Terima kasih atas jawabannya! Apa yang berubah menjadi nilai pakai daripada metode yang dijelaskan oleh joris?
xav
@xav valueadalah parameter pertama, jadi joris sebenarnya melakukan hal yang persis sama. Seperti yang dia katakan, lihat dokumennya .
chrisaycock
Ya, docstring agak menyesatkan karena methodtercantum di sana terlebih dahulu.
joris
7

pandas.DataFrame.combine_first juga berfungsi.

( Perhatian: karena "Kolom indeks hasil akan menjadi gabungan dari masing-masing indeks dan kolom", Anda harus memeriksa indeks dan kolom cocok. )

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

Bandingkan dengan jawaban lain:

%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)

Saya tidak menggunakan metode ini di bawah:

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)

karena itu akan memunculkan Exception:

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')

yang berarti np.isnan dapat diterapkan ke array NumPy dari dtype asli (seperti np.float64), tetapi memunculkan TypeError saat diterapkan ke array objek .

Jadi saya merevisi metode:

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)
Jeremy Z
sumber
0

Berikut adalah pendekatan yang lebih umum (metode fillna mungkin lebih baik)

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)
burung gereja
sumber
0

Saya tahu ini adalah pertanyaan lama, tetapi saya memiliki kebutuhan untuk melakukan hal serupa baru-baru ini. Saya bisa menggunakan yang berikut ini:

df = pd.DataFrame([["1","cat","mouse"],
    ["2","dog","elephant"],
    ["3","cat","giraf"],
    ["4",np.nan,"ant"]],columns=["Day","Cat1","Cat2"])

print(df)

  Day Cat1      Cat2
0   1  cat     mouse
1   2  dog  elephant
2   3  cat     giraf
3   4  NaN       ant

df1 = df.bfill(axis=1).iloc[:, 1]
df1 = df1.to_frame()
print(df1)

Hasil yang mana:

  Cat1
0  cat
1  dog
2  cat
3  ant

Semoga ini bermanfaat bagi seseorang!

Jeff Coldplume
sumber