Menghapus nilai nan dari array

223

Saya ingin mencari cara untuk menghapus nilai-nilai nan dari array saya. Array saya terlihat seperti ini:

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

Bagaimana cara menghapus nannilai dari x?

Dax Feliz
sumber
Agar lebih jelas, dengan "menghapus NaNs" yang Anda maksud hanya memfilter subset dari nilai-nilai yang bukan nol . Bukan "mengisi NaN dengan beberapa nilai (nol, konstan, rata-rata, median, dll.)"
smci

Jawaban:

362

Jika Anda menggunakan numpy untuk array Anda, Anda juga dapat menggunakan

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

Setara

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

[Terima kasih sudah menambahkan singkatan yang ditambahkan]

Penjelasan

Fungsi dalam, numpy.isnanmengembalikan array boolean / logis yang memiliki nilai di Truemana-mana yang xbukan-angka. Seperti yang kita inginkan sebaliknya, kita menggunakan operator logical-not, ~untuk mendapatkan array dengan Trues di mana-mana yang x merupakan angka yang valid.

Terakhir kami menggunakan array logis ini untuk mengindeks ke dalam array asli x, untuk mengambil hanya nilai-nilai non-NaN.

Jmetz
sumber
31
Ataux = x[numpy.isfinite(x)]
lazy1
14
Atau x = x[~numpy.isnan(x)], yang setara dengan jawaban asli mutzmatron, tetapi lebih pendek. Jika Anda ingin menjaga ketidakterbatasan Anda, ketahuilah numpy.isfinite(numpy.inf) == False, tentu saja, tetapi ~numpy.isnan(numpy.inf) == True.
chbrown
8
Bagi orang yang ingin menyelesaikan ini dengan ndarray dan mempertahankan dimensi, gunakan numpy di mana :np.where(np.isfinite(x), x, 0)
BoltzmannBrain
1
TypeError: hanya array skalar integer yang dapat dikonversi ke indeks skalar
towry
1
@towry: ini terjadi karena input Anda, xbukan array yang numpy. Jika Anda ingin menggunakan pengindeksan logis, itu harus berupa array - misalnyax = np.array(x)
jmetz
50
filter(lambda v: v==v, x)

berfungsi baik untuk daftar dan array numpy karena v! = v hanya untuk NaN

udibr
sumber
5
Retasan tetapi yang sangat berguna dalam kasus di mana Anda memfilter nans dari array objek dengan tipe campuran, seperti string dan nans.
Austin Richardson
Solusi yang sangat bersih.
Moondra
2
Ini mungkin tampak pintar, tetapi jika mengaburkan logika dan objek lain secara teoritis (seperti kelas khusus) juga dapat memiliki properti ini
Chris_Rands
Juga berguna karena hanya perlu xditentukan sekali sebagai lawan dari solusi jenis x[~numpy.isnan(x)]. Ini nyaman ketika xdidefinisikan oleh ekspresi panjang dan Anda tidak ingin mengacaukan kode dengan membuat variabel sementara untuk menyimpan hasil dari ekspresi panjang ini.
Christian O'Reilly
34

Coba ini:

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

Untuk lebih lanjut, baca tentang Pemahaman Daftar .

liori
sumber
5
Jika Anda menggunakan numpy baik jawaban saya dan bahwa dengan @ lazy1 hampir urutan besarnya lebih cepat daripada pemahaman daftar - solusi lazy1 sedikit lebih cepat (meskipun secara teknis juga tidak akan mengembalikan nilai tak terhingga).
jmetz
Jangan lupa tanda kurung :)print ([value for value in x if not math.isnan(value)])
hypers
Jika Anda menggunakan numpy seperti jawaban teratas maka Anda dapat menggunakan jawaban pemahaman daftar ini dengan nppaket: Jadi kembalikan daftar Anda tanpa [value for value in x if not np.isnan(value)]
nans
23

Bagi saya jawaban oleh @jmetz tidak bekerja, namun menggunakan panda isnull () berhasil.

x = x[~pd.isnull(x)]
Daniel Kislyuk
sumber
6

Melakukan hal di atas:

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

atau

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

Saya menemukan bahwa pengaturan ulang ke variabel yang sama (x) tidak menghapus nilai nan aktual dan harus menggunakan variabel yang berbeda. Mengaturnya ke variabel yang berbeda menghapus nans. misalnya

y = x[~numpy.isnan(x)]
melissaOu
sumber
Ini aneh; menurut dokumen , pengindeksan boolean array (yang ini), berada di bawah pengindeksan lanjutan yang tampaknya "selalu mengembalikan salinan data", jadi Anda harus menulis berlebihan xdengan nilai baru (yaitu tanpa NaNs ...) . Bisakah Anda memberikan info lebih lanjut mengapa ini bisa terjadi?
jmetz
5

Seperti yang ditunjukkan oleh orang lain

x[~numpy.isnan(x)]

bekerja. Tapi itu akan menimbulkan kesalahan jika tipe numpy bukan tipe data asli, misalnya jika objek. Dalam hal ini Anda dapat menggunakan panda.

x[~pandas.isna(x)] or x[~pandas.isnull(x)]
koliyat9811
sumber
4

The jawaban yang diterima berubah bentuk untuk array 2d. Saya menyajikan solusi di sini, menggunakan fungsionalitas dropna () Pandas . Ini bekerja untuk array 1D dan 2D. Dalam kasus 2D Anda dapat memilih cuaca untuk menjatuhkan baris atau kolom yang berisi 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='')

Hasil:

==================== 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.]
Markus Dutschke
sumber
3

Jika Anda menggunakan numpy

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

# second get the values
x = x[ii]
aloha
sumber
0

Ini adalah pendekatan saya untuk menyaring ndarray "X" untuk NaNs dan infs,

Saya membuat peta baris tanpa NaNdan apa pun infsebagai berikut:

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

idx adalah tuple. Ini kolom kedua ( idx[1]) berisi indeks array, di mana tidak ada NaN atau inf di mana ditemukan di sepanjang baris.

Kemudian:

filtered_X = X[idx[1]]

filtered_Xberisi X tanpa NaN atau inf.

aerijman
sumber
0

@ jawaban jmetz mungkin yang paling dibutuhkan orang; namun ia menghasilkan array satu dimensi, misalnya membuatnya tidak dapat digunakan untuk menghapus seluruh baris atau kolom dalam matriks.

Untuk melakukannya, kita harus mengurangi larik logis menjadi satu dimensi, lalu mengindeks larik target. Misalnya, berikut ini akan menghapus baris yang memiliki setidaknya satu nilai NaN:

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

Lihat lebih detail di sini .

M4urice
sumber