2015-01-12 40 views
36

Giả sử tôi có một DataFrame với một số NaN s:Làm thế nào để thay thế NaN bằng các giá trị trước trong gấu trúc DataFrame?

>>> import pandas as pd 
>>> df = pd.DataFrame([[1, 2, 3], [4, None, None], [None, None, 9]]) 
>>> df 
    0 1 2 
0 1 2 3 
1 4 NaN NaN 
2 NaN NaN 9 

Những gì tôi cần phải làm là thay thế mỗi NaN với NaN giá trị phi đầu tiên trong cùng một cột trên nó. Giả sử rằng hàng đầu tiên sẽ không bao giờ chứa NaN. Vì vậy, cho ví dụ trước kết quả sẽ là

0 1 2 
0 1 2 3 
1 4 2 3 
2 4 2 9 

tôi có thể chỉ là vòng lặp thông qua toàn bộ DataFrame cột-by-cột, yếu tố-by-phần tử và thiết lập các giá trị trực tiếp, nhưng là có một cách dễ dàng (tối ưu một vòng lặp - miễn phí) cách để đạt được điều này?

Trả lời

59

Bạn có thể sử dụng phương pháp fillna trên DataFrame và chỉ định phương pháp như ffill (forward điền):

>>> df = pd.DataFrame([[1, 2, 3], [4, None, None], [None, None, 9]]) 
>>> df.fillna(method='ffill') 
    0 1 2 
0 1 2 3 
1 4 2 3 
2 4 2 9 

Phương pháp này ...

Tuyên truyền [s] quan sát hợp lệ cuối cùng về phía trước tiếp theo hợp lệ

Để đi ngược lại, cũng có phương thức bfill.

Phương pháp này không thay đổi inplace DataFrame - bạn sẽ cần phải rebind DataFrame trở lại một biến hoặc nếu không xác định inplace=True:

df.fillna(method='ffill', inplace=True) 
9

Bạn có thể sử dụng pandas.DataFrame.fillna với các tùy chọn method='ffill'. 'ffill' là viết tắt của 'chuyển tiếp điền' và sẽ tuyên truyền quan sát hợp lệ cuối cùng về phía trước. Cách thay thế là 'bfill' hoạt động theo cùng một cách nhưng ngược lại.

import pandas as pd 

df = pd.DataFrame([[1, 2, 3], [4, None, None], [None, None, 9]]) 
df = df.fillna(method='ffill') 

print(df) 
# 0 1 2 
#0 1 2 3 
#1 4 2 3 
#2 4 2 9 

Ngoài ra còn có chức năng đồng nghĩa trực tiếp cho điều này, pandas.DataFrame.ffill, để làm cho mọi việc đơn giản hơn.

2

Một điều mà tôi nhận thấy khi thử giải pháp này là nếu bạn có N/A lúc bắt đầu hoặc kết thúc mảng, thì việc điền và điền vào không hoàn toàn hoạt động. Bạn cần cả hai.

In [224]: df = pd.DataFrame([None, 1, 2, 3, None, 4, 5, 6, None]) 

In [225]: df.ffill() 
Out[225]: 
    0 
0 NaN 
1 1.0 
... 
7 6.0 
8 6.0 

In [226]: df.bfill() 
Out[226]: 
    0 
0 1.0 
1 1.0 
... 
7 6.0 
8 NaN 

In [227]: df.bfill().ffill() 
Out[227]: 
    0 
0 1.0 
1 1.0 
... 
7 6.0 
8 6.0 
4

Câu trả lời được chấp nhận là hoàn hảo. Tôi đã có một tình huống liên quan nhưng hơi khác một chút, nơi tôi phải điền vào phía trước nhưng chỉ trong nhóm. Trong trường hợp ai đó có cùng nhu cầu, biết rằng fillna hoạt động trên một đối tượng DataFrameGroupBy.

>>> example = pd.DataFrame({'number':[0,1,2,nan,4,nan,6,7,8,9],'name':list('aaabbbcccc')}) 
>>> example 
    name number 
0 a  0.0 
1 a  1.0 
2 a  2.0 
3 b  NaN 
4 b  4.0 
5 b  NaN 
6 c  6.0 
7 c  7.0 
8 c  8.0 
9 c  9.0 
>>> example.groupby('name')['number'].fillna(method='ffill') # fill in row 5 but not row 3 
0 0.0 
1 1.0 
2 2.0 
3 NaN 
4 4.0 
5 4.0 
6 6.0 
7 7.0 
8 8.0 
9 9.0 
Name: number, dtype: float64 
+0

chính xác những gì tôi đang tìm kiếm, ty – Tony

Các vấn đề liên quan