HOWTO · Python

Python のリストから NaN を削除する

このチュートリアルでは、Python のリストから NaN を削除する方法を示します。

このページの内容

NaN は、未定義または表現できない数値の結果を表すためによく使われる、浮動小数点数の特殊な値です。通常の文字列 'nan' とは異なります。数値のリストには Python の math.isnan()、数値配列には NumPy の numpy.isnan() が便利です。文字列の 'nan' を削除する場合は、文字列を直接比較します。数値の NaN と文字列の 'nan' の両方が含まれる混在データでは、pandas.isnull() と文字列比較を組み合わせます。

Python のリストから math.isnan() で NaN を削除する

Python 標準ライブラリの math.isnan() 関数は、数値の NaN を判定します。これはメソッドではなく関数です。NaN は自分自身とも等しくないため、x != x のような判定でも検出できますが、math.isnan() を使うと意図が明確になります。この方法は、math.isnan() が受け取れる数値を含むリストに使ってください。任意の文字列やオブジェクトに使える汎用的な判定ではありません。なお、math.isnan() の日本語版リンク先は用意されていないため、英語版のリファレンスを参照してください。

次の例では数値のリストをフィルタリングし、元のリストは変更しません。

import math

values = [1, 2, float("nan"), 4]
without_nan = [value for value in values if not math.isnan(value)]
print(without_nan)
[1, 2, 4]

Python のリストから numpy.isnan() で NaN を削除する

NumPy をすでにプロジェクトで使っている場合、numpy.isnan() を使うとリストや配列の数値をまとめて判定できます。必要であれば python -m pip install numpy で NumPy をインストールしてください。この例では入力を配列に変換し、真偽値のマスクを作成して、NaN ではない値を選択した後、結果を Python のリストに戻します。そのため、最終結果は NumPy 配列ではなくリストです。

import numpy as np

values = [1, 2, np.nan, 4]
array = np.array(values)
without_nan = array[~np.isnan(array)].tolist()
print(without_nan)
[1.0, 2.0, 4.0]

Python のリストから文字列 'nan' を削除する

文字列の 'nan' は通常のテキストであり、浮動小数点数の NaN ではありません。データがすでに文字列のリストなら、各要素を直接比較して、完全に一致する小文字の 'nan' を削除します。これにより、残す要素の型と表記はそのまま保たれます。データで大文字・小文字や空白の扱いが異なる場合は、比較条件を調整してください。

values = ["1", "2", "nan", "8"]
without_string_nan = [value for value in values if value != "nan"]
print(without_string_nan)
['1', '2', '8']

各要素を先に str() で文字列に変換すると、残す数値も文字列になります。データの形式をそろえる場合には便利ですが、結果の型が変わります。リスト内の文字列を削除するだけなら、この変換は必要ありません。

混在する Python のリストから pandas.isnull() で NaN と文字列 'nan' を削除する

数値と文字列が混在するリストでは、pandas.isnull() で数値の NaN などの欠損値を判定し、文字列 'nan' は別の条件で比較します。pandas.isnull() はテキストの 'nan' を欠損値とは判定しません。次の例には pandas が必要です。必要であれば python -m pip install pandas でインストールしてください。この方法では、残す他の文字列や数値の型を維持できます。pandas.isnull() のリファレンスでは、欠損値の判定について説明しています。

import pandas as pd

values = ["Ada", 23, "nan", "London", float("nan")]
without_missing_or_string_nan = [
    value
    for value in values
    if not pd.isnull(value) and value != "nan"
]
print(without_missing_or_string_nan)
['Ada', 23, 'London']