配列からナン値を削除する


223

配列からナン値を削除する方法を理解したいと思います。私の配列は次のようになります:

x = [1400, 1500, 1600, nan, nan, nan ,1700] #Not in this exact configuration

nanから値を削除するにはどうすればよいxですか?


明確にするために、「NaNを削除する」とは、null以外の値のサブセットのみを除外することを意味します。「NaNに何らかの値(ゼロ、定数、平均、中央値など)を入力する」
-smci

回答:


362

numpyを配列に使用している場合は、

x = x[numpy.logical_not(numpy.isnan(x))]

同等に

x = x[~numpy.isnan(x)]

[追加された省略表現についてchbrownに感謝]

説明

内部関数numpy.isnanは、数値Truexはないあらゆる場所に値を持つブール/論理配列を返します。反対が欲しいので、論理的否定演算子を使用して、有効な数値あるすべての場所にsを~含む配列を取得します。Truex

最後に、この論理配列を使用して元の配列にインデックスを付け、xNaN以外の値のみを取得します。


31
またはx = x[numpy.isfinite(x)]
lazy1 2012

14
またはx = x[~numpy.isnan(x)]、これはmutzmatronの元の回答と同等ですが、短くなります。無限を維持したい場合numpy.isfinite(numpy.inf) == Falseは、もちろんそれを知っておいてください~numpy.isnan(numpy.inf) == True
chbrown 2013年

8
ndarrayでこれを解決し、寸法を維持し、使用するために探している人々のためにnumpyのnp.where(np.isfinite(x), x, 0)
BoltzmannBrain

1
TypeError:整数のスカラー配列のみがスカラーインデックスに変換できます
towry

1
@towry:これは、入力が派手なx配列ではないために発生しています。論理インデックスを使用する場合は、配列にする必要があります-例x = np.array(x)
jmetz

50
filter(lambda v: v==v, x)

NaNの場合のみv!= vなので、リストとnumpy配列の両方で機能します


5
ハックですが、文字列とナンなど、タイプが混在するオブジェクトの配列からナンをフィルタリングする場合に特に便利です。
オースティンリチャードソン

非常にきれいなソリューション。
Moondra

2
これは賢いように見えるかもしれませんが、ロジックが
曖昧

xタイプのソリューションとは対照的に、一度だけ指定する必要があるため、これも役立ちますx[~numpy.isnan(x)]。これはx、長い式で定義されていて、この長い式の結果を格納する一時変数を作成してコードを煩雑にしたくない場合に便利です。
クリスチャンオライリー

34

これを試して:

import math
print [value for value in x if not math.isnan(value)]

詳細については、リスト内包表記をご覧ください。


5
numpyを使用している場合、私の回答と@ lazy1による回答の両方がリスト内包よりもほぼ1桁高速です-lazy1のソリューションは少し高速です(技術的には無限値も返されません)。
jmetz 2012

括弧を忘れないでください:)print ([value for value in x if not math.isnan(value)])
hypers

あなたは、トップの答えのようなnumpyのを使用している場合は、あなたがこのリスト内包答えを使用することができますnpパッケージ:だからはNaNをせずに、あなたのリストを返します:[value for value in x if not np.isnan(value)]
yeliabsalohcin


6

上記を行う:

x = x[~numpy.isnan(x)]

または

x = x[numpy.logical_not(numpy.isnan(x))]

同じ変数(x)にリセットしても実際のnan値は削除されず、別の変数を使用する必要があることがわかりました。別の変数に設定すると、ナンが削除されました。例えば

y = x[~numpy.isnan(x)]

これは奇妙です; docsによると、ブール配列のインデックス付け(これは)は高度なインデックス付けの下にあり、明らかに「常にデータのコピーを返す」ためx、新しい値で上書きする必要があります(つまり、NaNなし...) 。なぜこれが起こり得るのかについて、もっと詳しい情報を提供できますか?
jmetz 2017年

5

他の人が示すように

x[~numpy.isnan(x)]

動作します。しかし、numpy dtypeがネイティブデータ型でない場合、たとえばオブジェクトである場合は、エラーがスローされます。その場合、パンダを使用できます。

x[~pandas.isna(x)] or x[~pandas.isnull(x)]

4

受け入れ答えは、2Dアレイの形状を変化させます。ここでは、Pandasのdropna()機能を使用したソリューションを紹介します。1Dおよび2Dアレイで機能します。2Dの場合、天候を選択してを含む行または列ドロップできますnp.nan

import pandas as pd
import numpy as np

def dropna(arr, *args, **kwarg):
    assert isinstance(arr, np.ndarray)
    dropped=pd.DataFrame(arr).dropna(*args, **kwarg).values
    if arr.ndim==1:
        dropped=dropped.flatten()
    return dropped

x = np.array([1400, 1500, 1600, np.nan, np.nan, np.nan ,1700])
y = np.array([[1400, 1500, 1600], [np.nan, 0, np.nan] ,[1700,1800,np.nan]] )


print('='*20+' 1D Case: ' +'='*20+'\nInput:\n',x,sep='')
print('\ndropna:\n',dropna(x),sep='')

print('\n\n'+'='*20+' 2D Case: ' +'='*20+'\nInput:\n',y,sep='')
print('\ndropna (rows):\n',dropna(y),sep='')
print('\ndropna (columns):\n',dropna(y,axis=1),sep='')

print('\n\n'+'='*20+' x[np.logical_not(np.isnan(x))] for 2D: ' +'='*20+'\nInput:\n',y,sep='')
print('\ndropna:\n',x[np.logical_not(np.isnan(x))],sep='')

結果:

==================== 1D Case: ====================
Input:
[1400. 1500. 1600.   nan   nan   nan 1700.]

dropna:
[1400. 1500. 1600. 1700.]


==================== 2D Case: ====================
Input:
[[1400. 1500. 1600.]
 [  nan    0.   nan]
 [1700. 1800.   nan]]

dropna (rows):
[[1400. 1500. 1600.]]

dropna (columns):
[[1500.]
 [   0.]
 [1800.]]


==================== x[np.logical_not(np.isnan(x))] for 2D: ====================
Input:
[[1400. 1500. 1600.]
 [  nan    0.   nan]
 [1700. 1800.   nan]]

dropna:
[1400. 1500. 1600. 1700.]

3

使用している場合 numpy

# first get the indices where the values are finite
ii = np.isfinite(x)

# second get the values
x = x[ii]


0

これは、NaNおよびinfsのndarray "X" をフィルターする私のアプローチです。

次のようにNaN、何もない行のマップを作成infします。

idx = np.where((np.isnan(X)==False) & (np.isinf(X)==False))

idxはタプルです。2番目の列(idx[1])には配列のインデックスが含まれ、行全体でNaNinfも見つかりません。

次に:

filtered_X = X[idx[1]]

filtered_Xnor なしの Xが含まれています。NaNinf


0

@jmetzの答えはおそらくほとんどの人が必要とするものです。ただし、1次元配列が生成されます。たとえば、行列の行または列全体を削除することができなくなります。

そのためには、論理配列を1次元に減らしてから、ターゲット配列にインデックスを付けます。たとえば、次は、少なくとも1つのNaN値を持つ行を削除します。

x = x[~numpy.isnan(x).any(axis=1)]

詳細はこちら

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.