Cách kiểm tra xem có giá trị nào là NaN trong Khung dữ liệu Pandas không


483

Trong Python Pandas, cách tốt nhất để kiểm tra xem DataFrame có một (hoặc nhiều) giá trị NaN không?

Tôi biết về hàm pd.isnan, nhưng điều này trả về một DataFrame của booleans cho mỗi phần tử. Bài đăng này ngay tại đây không trả lời chính xác câu hỏi của tôi.


Câu trả lời:


577

Phản ứng của jwilner là tại chỗ. Tôi đã khám phá để xem liệu có một lựa chọn nhanh hơn không, vì theo kinh nghiệm của tôi, việc tổng hợp các mảng phẳng nhanh hơn (lạ lùng) so với đếm. Mã này có vẻ nhanh hơn:

df.isnull().values.any()

Ví dụ:

In [2]: df = pd.DataFrame(np.random.randn(1000,1000))

In [3]: df[df > 0.9] = pd.np.nan

In [4]: %timeit df.isnull().any().any()
100 loops, best of 3: 14.7 ms per loop

In [5]: %timeit df.isnull().values.sum()
100 loops, best of 3: 2.15 ms per loop

In [6]: %timeit df.isnull().sum().sum()
100 loops, best of 3: 18 ms per loop

In [7]: %timeit df.isnull().values.any()
1000 loops, best of 3: 948 µs per loop

df.isnull().sum().sum()chậm hơn một chút, nhưng tất nhiên, có thêm thông tin - số lượng NaNs.


1
Cảm ơn bạn cho điểm chuẩn thời gian. Thật đáng ngạc nhiên khi pandaskhông có chức năng tích hợp cho việc này. Đó là sự thật từ bài đăng của @ JGreenwell df.describe()có thể làm điều này, nhưng không có chức năng trực tiếp.
hlin117

2
Tôi chỉ hẹn giờ df.describe()(không tìm thấy NaNs). Với mảng 1000 x 1000, một cuộc gọi sẽ mất 1,15 giây.
hlin117

3
: 1, Ngoài ra, df.isnull().values.sum()nhanh hơn một chút so vớidf.isnull().values.flatten().sum()
Zero

À, bắt tốt @JohnGalt - Tôi sẽ thay đổi giải pháp của mình để xóa bài .flatten()đăng. Cảm ơn.
S Anand

6
Bạn đã không thử df.isnull().values.any(), đối với tôi nó nhanh hơn những người khác.
CK1

178

Bạn có một cặp đôi tùy chọn.

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randn(10,6))
# Make a few areas have NaN values
df.iloc[1:3,1] = np.nan
df.iloc[5,3] = np.nan
df.iloc[7:9,5] = np.nan

Bây giờ khung dữ liệu trông giống như thế này:

          0         1         2         3         4         5
0  0.520113  0.884000  1.260966 -0.236597  0.312972 -0.196281
1 -0.837552       NaN  0.143017  0.862355  0.346550  0.842952
2 -0.452595       NaN -0.420790  0.456215  1.203459  0.527425
3  0.317503 -0.917042  1.780938 -1.584102  0.432745  0.389797
4 -0.722852  1.704820 -0.113821 -1.466458  0.083002  0.011722
5 -0.622851 -0.251935 -1.498837       NaN  1.098323  0.273814
6  0.329585  0.075312 -0.690209 -3.807924  0.489317 -0.841368
7 -1.123433 -1.187496  1.868894 -2.046456 -0.949718       NaN
8  1.133880 -0.110447  0.050385 -1.158387  0.188222       NaN
9 -0.513741  1.196259  0.704537  0.982395 -0.585040 -1.693810
  • Tùy chọn 1 : df.isnull().any().any()- Điều này trả về giá trị boolean

Bạn biết cái isnull()nào sẽ trả về một khung dữ liệu như thế này:

       0      1      2      3      4      5
0  False  False  False  False  False  False
1  False   True  False  False  False  False
2  False   True  False  False  False  False
3  False  False  False  False  False  False
4  False  False  False  False  False  False
5  False  False  False   True  False  False
6  False  False  False  False  False  False
7  False  False  False  False  False   True
8  False  False  False  False  False   True
9  False  False  False  False  False  False

Nếu bạn tạo nó df.isnull().any(), bạn chỉ có thể tìm thấy các cột có NaNgiá trị:

0    False
1     True
2    False
3     True
4    False
5     True
dtype: bool

Một người nữa .any()sẽ cho bạn biết nếu có bất kỳ điều nào ở trênTrue

> df.isnull().any().any()
True
  • Tùy chọn 2 : df.isnull().sum().sum()- Điều này trả về một số nguyên của tổng số NaNgiá trị:

Điều này hoạt động theo cách tương tự như trước .any().any(), bằng cách trước tiên đưa ra tổng của số lượng NaNgiá trị trong một cột, sau đó là tổng của các giá trị đó:

df.isnull().sum()
0    0
1    2
2    0
3    1
4    0
5    2
dtype: int64

Cuối cùng, để có được tổng số giá trị NaN trong DataFrame:

df.isnull().sum().sum()
5

Tại sao không sử dụng .any(axis=None)thay vì .any().any()?
Georgy

57

Để tìm ra hàng nào có NaN trong một cột cụ thể:

nan_rows = df[df['name column'].isnull()]

17
Để tìm ra những hàng nào không có NaN trong một cột cụ thể : non_nan_rows = df[df['name column'].notnull()].
Elmex80s

49

Nếu bạn cần biết có bao nhiêu hàng với "một hoặc nhiều NaNs":

df.isnull().T.any().T.sum()

Hoặc nếu bạn cần kéo ra các hàng này và kiểm tra chúng:

nan_rows = df[df.isnull().T.any().T]

4
Tôi nghĩ rằng chúng ta không cần T
YOBEN_S


18

Thêm vào câu trả lời xuất sắc của Hobs, tôi rất mới với Python và Pandas vì vậy xin vui lòng chỉ ra nếu tôi sai.

Để tìm ra hàng nào có NaN:

nan_rows = df[df.isnull().any(1)]

sẽ thực hiện thao tác tương tự mà không cần chuyển vị bằng cách chỉ định trục của bất kỳ () nào là 1 để kiểm tra xem 'True' có xuất hiện trong các hàng hay không.


Điều này được loại bỏ hai chuyển! Yêu any(axis=1)đơn giản hóa súc tích của bạn .
hobs

12

Cú pháp siêu đơn giản: df.isna().any(axis=None)

Bắt đầu từ v0.23.2 , bạn có thể sử dụng DataFrame.isna+ DataFrame.any(axis=None)trong đó axis=Nonechỉ định giảm logic trên toàn bộ DataFrame.

# Setup
df = pd.DataFrame({'A': [1, 2, np.nan], 'B' : [np.nan, 4, 5]})
df
     A    B
0  1.0  NaN
1  2.0  4.0
2  NaN  5.0

df.isna()

       A      B
0  False   True
1  False  False
2   True  False

df.isna().any(axis=None)
# True

Lựa chọn thay thế hữu ích

numpy.isnan
Một tùy chọn biểu diễn khác nếu bạn đang chạy phiên bản cũ hơn của gấu trúc.

np.isnan(df.values)

array([[False,  True],
       [False, False],
       [ True, False]])

np.isnan(df.values).any()
# True

Hoặc, kiểm tra tổng:

np.isnan(df.values).sum()
# 2

np.isnan(df.values).sum() > 0
# True

Series.hasnans
Bạn cũng có thể gọi lặp lại Series.hasnans. Ví dụ: để kiểm tra xem một cột có NaN không,

df['A'].hasnans
# True

Và để kiểm tra xem cột nào có NaN không, bạn có thể sử dụng mức độ hiểu với any(đó là thao tác ngắn mạch).

any(df[c].hasnans for c in df)
# True

Điều này thực sự rất nhanh.


10

Vì không có ai đề cập, chỉ có một biến khác được gọi là hasnans .

df[i].hasnanssẽ xuất ra Truenếu một hoặc nhiều giá trị trong Sê-ri gấu trúc là NaN, Falsenếu không. Lưu ý rằng nó không phải là một chức năng.

phiên bản gấu trúc '0.19.2' và '0.20.2'


6
Câu trả lời này không chính xác. Dòng Pandas có thuộc tính này nhưng DataFrames thì không. Nếu df = DataFrame([1,None], columns=['foo']), sau đó df.hasnanssẽ ném một AttributeError, nhưng df.foo.hasnanssẽ trở lại True.
Nathan Thompson

7

pandasphải tìm ra điều này DataFrame.dropna(), tôi đã xem thử cách họ thực hiện nó và phát hiện ra rằng họ đã sử dụng DataFrame.count(), trong đó đếm tất cả các giá trị khác không trong DataFrame. Cf. mã nguồn gấu trúc . Tôi đã không điểm chuẩn kỹ thuật này, nhưng tôi cho rằng các tác giả của thư viện có thể đã có một lựa chọn sáng suốt cho cách thực hiện nó.


6

hãy dflà tên của Pandas DataFrame và bất kỳ giá trị nào là numpy.nangiá trị null.

  1. Nếu bạn muốn xem cột nào có null và cột nào không (chỉ Đúng và Sai)
    df.isnull().any()
  2. Nếu bạn chỉ muốn xem các cột có null
    df.loc[:, df.isnull().any()].columns
  3. Nếu bạn muốn xem số lượng null trong mỗi cột
    df.isna().sum()
  4. Nếu bạn muốn xem tỷ lệ phần trăm rỗng trong mỗi cột

    df.isna().sum()/(len(df))*100
  5. Nếu bạn muốn xem phần trăm null trong các cột chỉ với null: df.loc[:,list(df.loc[:,df.isnull().any()].columns)].isnull().sum()/(len(df))*100

CHỈNH SỬA 1:

Nếu bạn muốn xem dữ liệu của bạn bị thiếu ở đâu:

import missingno
missingdata_df = df.columns[df.isnull().any()].tolist()
missingno.matrix(df[missingdata_df])

Nếu bạn muốn thấy số lượng null trong mỗi cột ... Điều đó có vẻ điên rồ, tại sao không làm df.isna().sum()?
AMC

4

Chỉ cần sử dụng math.isnan (x) , Trả về True nếu x là NaN (không phải số) và Sai khác.


4
Tôi không nghĩ math.isnan(x)sẽ hoạt động khi xDataFrame. Bạn nhận được một TypeError thay thế.
hlin117

Tại sao bạn sẽ sử dụng điều này trên bất kỳ lựa chọn thay thế?
AMC

4
df.isnull().sum()

Điều này sẽ cung cấp cho bạn số lượng tất cả các giá trị NaN có trong các coloums tương ứng của DataFrame.


Không, điều đó sẽ cung cấp cho bạn một Chuỗi ánh xạ tên cột theo số giá trị NA tương ứng của chúng.
AMC

Đã sửa, lỗi của tôi: p
Adarsh ​​singh

3

Đây là một cách thú vị khác để tìm null và thay thế bằng giá trị được tính

    #Creating the DataFrame

    testdf = pd.DataFrame({'Tenure':[1,2,3,4,5],'Monthly':[10,20,30,40,50],'Yearly':[10,40,np.nan,np.nan,250]})
    >>> testdf2
       Monthly  Tenure  Yearly
    0       10       1    10.0
    1       20       2    40.0
    2       30       3     NaN
    3       40       4     NaN
    4       50       5   250.0

    #Identifying the rows with empty columns
    nan_rows = testdf2[testdf2['Yearly'].isnull()]
    >>> nan_rows
       Monthly  Tenure  Yearly
    2       30       3     NaN
    3       40       4     NaN

    #Getting the rows# into a list
    >>> index = list(nan_rows.index)
    >>> index
    [2, 3]

    # Replacing null values with calculated value
    >>> for i in index:
        testdf2['Yearly'][i] = testdf2['Monthly'][i] * testdf2['Tenure'][i]
    >>> testdf2
       Monthly  Tenure  Yearly
    0       10       1    10.0
    1       20       2    40.0
    2       30       3    90.0
    3       40       4   160.0
    4       50       5   250.0

3

Tôi đã sử dụng cách sau đây và nhập truyền chuỗi thành chuỗi và kiểm tra giá trị nan

   (str(df.at[index, 'column']) == 'nan')

Điều này cho phép tôi kiểm tra giá trị cụ thể trong một chuỗi và không chỉ trả về nếu giá trị này được chứa ở đâu đó trong chuỗi.


Có bất kỳ lợi thế để sử dụng này hơn pandas.isna()?
AMC

2

Tốt nhất sẽ là sử dụng:

df.isna().any().any()

Đây là lý do tại sao . Vì vậy, isna()được sử dụng để định nghĩa isnull(), nhưng tất cả cả hai đều giống hệt nhau.

Điều này thậm chí còn nhanh hơn câu trả lời được chấp nhận và bao gồm tất cả các mảng gấu trúc 2D.


1

Hoặc bạn có thể sử dụng .info()trênDF như:

df.info(null_counts=True) trong đó trả về số lượng hàng không có tên trong một cột như:

<class 'pandas.core.frame.DataFrame'>
Int64Index: 3276314 entries, 0 to 3276313
Data columns (total 10 columns):
n_matches                          3276314 non-null int64
avg_pic_distance                   3276314 non-null float64


0
df.apply(axis=0, func=lambda x : any(pd.isnull(x)))

Sẽ kiểm tra từng cột nếu nó có chứa Nan hay không.


Tại sao sử dụng điều này trên bất kỳ giải pháp dựng sẵn?
AMC

0

Chúng ta có thể thấy các giá trị null có trong tập dữ liệu bằng cách tạo bản đồ nhiệt bằng cách sử dụng bản đồ nhiệt mô-đun seaborn

import pandas as pd
import seaborn as sns
dataset=pd.read_csv('train.csv')
sns.heatmap(dataset.isnull(),cbar=False)

-1

Bạn không chỉ kiểm tra xem có tồn tại 'NaN' hay không mà còn nhận được tỷ lệ phần trăm của 'NaN' trong mỗi cột bằng cách sử dụng như sau,

df = pd.DataFrame({'col1':[1,2,3,4,5],'col2':[6,np.nan,8,9,10]})  
df  

   col1 col2  
0   1   6.0  
1   2   NaN  
2   3   8.0  
3   4   9.0  
4   5   10.0  


df.isnull().sum()/len(df)  
col1    0.0  
col2    0.2  
dtype: float64

-2

Tùy thuộc vào loại dữ liệu bạn đang xử lý, bạn cũng có thể nhận được tổng giá trị của từng cột trong khi thực hiện EDA của mình bằng cách đặt dropna thành Sai.

for col in df:
   print df[col].value_counts(dropna=False)

Hoạt động tốt cho các biến phân loại, không quá nhiều khi bạn có nhiều giá trị duy nhất.


Tôi nghĩ rằng điều này là không hiệu quả. Các chức năng tích hợp của gấu trúc gọn gàng / ngắn gọn hơn. Tránh làm lộn xộn máy tính xách tay ipython.
Koo

Không có điểm nào trong việc sử dụng điều này trên các giải pháp tích hợp.
AMC
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.