Cách chuyển toàn bộ cột khác làm đối số cho pandas fillna ()


94

Tôi muốn điền các giá trị còn thiếu vào một cột với các giá trị từ một cột khác, bằng fillnaphương pháp.

(Tôi đọc rằng việc lặp lại từng hàng sẽ là một cách thực hành rất tệ và tốt hơn là làm mọi thứ trong một lần nhưng tôi không thể tìm ra cách thực hiện fillna.)

Dữ liệu trước đây:

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

Dữ liệu sau:

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

Câu trả lời:


173

Bạn có thể cung cấp cột này cho fillna(xem tài liệu ), nó sẽ sử dụng các giá trị đó trên các chỉ mục phù hợp để điền:

In [17]: df['Cat1'].fillna(df['Cat2'])
Out[17]:
0    cat
1    dog
2    cat
3    ant
Name: Cat1, dtype: object

7
Đẹp! Tôi không biết rằng fillnaphải mất một loạt.
Ami Tavory

1
Cảm ơn! Tôi nghĩ serie phải có kích thước chính xác của số giá trị NA.
xav

Nó cũng hoạt động cho khung dữ liệu cho các hàng đa cực. Tính năng đó của fillna rất hữu ích.
Wertikal

19

Bạn có thể làm

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

Cấu trúc tổng thể trên RHS sử dụng mẫu bậc ba từ pandassách dạy nấu ăn (mà nó trả tiền để đọc trong mọi trường hợp). Đó là một phiên bản vector của a? b: c.


Không phải là giải pháp tôi đã sử dụng cho vấn đề này mà là mô hình rất thú vị! Cảm ơn!
xav

có cách nào sử dụng cái này cho nhiều cột không? Ví dụ: nếu df này có cat1, cat2, cat3, cat4, cat5 và giả sử cat5 trống. có cách nào để điền cat5 với các giá trị từ cat1 nếu cat1 trống thì cat2, nếu cat2 trống thì cat3, v.v.?
user8322222 14/02/19

@ user8322222 Tôi chắc chắn đến muộn nhưng nếu ai đó có câu hỏi này, bạn có thể làm np.where lồng nhau, giống như bạn làm trong excel cell = np.where (cond, val_true, np.where (cond, val_true, val_false), ).
Kaisar

Bạn muốn đề cập rằng đây chỉ là xác định lại nội trang gấu trúc pd.DataFrame.fillna(). Và tôi nghi ngờ hành vi góc hợp cụ thể có thể khác nhau ví dụ như cho độ dài loạt không hạnh phúc từ dataframes khác nhau: DFA [ 'CAT1'], DFB [ 'Cat2']
SMCI

8

Chỉ cần sử dụng valuetham số thay vì 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

Cảm ơn vì câu trả lời! Nó thay đổi gì để sử dụng giá trị thay vì phương thức được mô tả bởi joris?
xav

@xav valuelà tham số đầu tiên, vì vậy joris thực sự đang làm điều tương tự. Như anh ấy nói, hãy xem tài liệu .
chrisaycock

Có, docstring có một chút sai lệch như methodđược liệt kê ở đó đầu tiên.
joris

7

pandas.DataFrame.combine_first cũng hoạt động.

( Chú ý: vì "Các cột chỉ mục kết quả sẽ là sự kết hợp của các chỉ mục và cột tương ứng", bạn nên kiểm tra chỉ mục và các cột có khớp không. )

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

So sánh với các câu trả lời khác:

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

Tôi đã không sử dụng phương pháp này bên dưới:

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)

bởi vì nó sẽ tăng một Ngoại lệ:

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

có nghĩa là np.isnan có thể được áp dụng cho các mảng NumPy của loại dtype gốc (chẳng hạn như np.float64), nhưng lại làm tăng TypeError khi áp dụng cho các mảng đối tượng .

Vì vậy, tôi sửa đổi phương pháp:

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)

0

Đây là một cách tiếp cận tổng quát hơn (phương pháp fillna có lẽ tốt hơ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)

0

Tôi biết đây là một câu hỏi cũ, nhưng gần đây tôi cần làm điều gì đó tương tự. Tôi đã có thể sử dụng những thứ sau:

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)

Kết quả là:

  Cat1
0  cat
1  dog
2  cat
3  ant

Hy vọng điều này là hữu ích cho ai đó!

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.