HOWTO · NumPy
如何從 NumPy 陣列中移除 NaN 值
了解如何在 Python 中從 NumPy 陣列移除 NaN 值
本頁內容
若要從 NumPy 陣列移除 NaN 元素,可以建立一個只會在元素不是 NaN 時為 True 的遮罩,再用它選取元素。對 NumPy 陣列而言,array[~np.isnan(array)] 是精簡的寫法。
在 NumPy 中使用 logical_not() 和 isnan() 函式移除 NaN 值
np.isnan(array) 會回傳布林陣列,並在元素為 NaN 的位置標示 True。np.logical_not() 會反轉這些布林值,因此產生的遮罩會在一般數值的位置為 True。布林索引會依照元素原本的順序保留符合條件的項目。對 NumPy 布林陣列來說,~ 運算子是較精簡的等效寫法。
以下範例示範這兩種寫法,也顯示輸入全是 NaN 或完全沒有 NaN 時的結果:
import numpy as np
values = np.array([1.0, np.nan, 3.0])
without_nan = values[np.logical_not(np.isnan(values))]
without_nan_short = values[~np.isnan(values)]
all_nan = np.array([np.nan, np.nan])
no_nan = np.array([1, 2, 3])
print(without_nan)
print(without_nan_short)
print(all_nan[~np.isnan(all_nan)])
print(no_nan[~np.isnan(no_nan)])
[1. 3.]
[1. 3.]
[]
[1 2 3]
這兩種遮罩會得到相同的篩選結果。輸入若全是 NaN,結果會是空陣列;輸入若不含 NaN,則會原樣保留。更多行為說明請參閱 np.logical_not() 官方文件與 np.isnan() 官方文件。
在 NumPy 中使用 isfinite() 函式移除 NaN 值
np.isfinite(array) 會建立一個在有限數值位置為 True 的遮罩。使用這個遮罩索引可以移除 NaN,但正無限大和負無限大也會一併移除。若你只想保留有限數值,適合使用這個函式;若只要移除 NaN 並保留正負無限大,則使用上面的反轉 np.isnan() 遮罩。數值型別的相關行為可參閱 np.isfinite() 官方文件。
使用 math.isnan() 移除 NaN 值
Python 標準函式庫中的 math.isnan() 一次檢查一個純量值。先以 import math 匯入模組。若陣列是一維數值陣列,可以用清單推導式建立布林遮罩:keep = [not math.isnan(value) for value in values],接著用 filtered = values[keep] 篩選陣列。這種方式會在 Python 中逐一走訪陣列元素;NumPy 函式則會直接對陣列運算。此寫法假設輸入是一維陣列,因為走訪多維陣列時,取得的是子陣列而不是純量數字。
使用 pandas.isnull() 移除 NaN 值
如果你的專案已使用 pandas,可以透過 import pandas as pd 匯入,並用 pd.isnull() 找出缺失值,再反轉遮罩:filtered = values[~pd.isnull(values)]。這是 pandas 函式,不是 NumPy 方法;若專案尚未使用 pandas,不必只為了這項操作額外安裝它。對於 pandas 支援的資料結構,若其中包含其他缺失值標記,pd.isnull() 也能辨識這些標記。請參閱既有的 pandas isnull() 說明。