Для ясности, под «удалить NaN» вы подразумеваете отфильтровать только подмножество ненулевых значений . Не «заполняйте NaN каким-либо значением (ноль, константа, среднее значение, медиана и т. Д.)»
smci
Ответы:
362
Если вы используете NumPy для своих массивов, вы также можете использовать
x = x[numpy.logical_not(numpy.isnan(x))]
эквивалентно
x = x[~numpy.isnan(x)]
[Спасибо chbrown за добавленную стенографию]
объяснение
Внутренняя функция numpy.isnanвозвращает логический / логический массив, значение которого Trueвезде xне является числом. Поскольку мы хотим обратного, мы используем оператор логического not, ~чтобы получить массив с Trues везде, который xявляется допустимым числом.
Наконец, мы используем этот логический массив для индексации в исходном массиве x, чтобы получить только значения, отличные от NaN.
Или x = x[~numpy.isnan(x)], что эквивалентно первоначальному ответу mutzmatron, но короче. Если вы хотите сохранить свою бесконечность, знайте numpy.isfinite(numpy.inf) == False, конечно, но ~numpy.isnan(numpy.inf) == True.
chbrown
8
Для тех, кто хочет решить эту проблему с помощью ndarray и сохранить размеры, используйте numpy где :np.where(np.isfinite(x), x, 0)
BoltzmannBrain
1
Ошибка типа: в скалярный индекс можно преобразовать только целочисленные скалярные массивы
towry
1
@towry: это происходит потому, что ваши входные данные xне являются массивом. Если вы хотите использовать логический индексирование, он должен быть массив - напримерx = np.array(x)
jmetz
50
filter(lambda v: v==v, x)
работает как для списков, так и для массива numpy, поскольку v! = v только для NaN
Хак, но особенно полезен в случае, когда вы фильтруете nans из массива объектов со смешанными типами, таких как строки и nans.
Остин Ричардсон
Очень чистое решение.
Мундра
2
Это может показаться умным, но если затеняет логику и теоретически другие объекты (такие как пользовательские классы) также могут иметь это свойство
Chris_Rands
Также полезно, потому что это должно xбыть указано только один раз, в отличие от решений типа x[~numpy.isnan(x)]. Это удобно, когда xопределяется длинным выражением, и вы не хотите загромождать код, создавая временную переменную для хранения результата этого длинного выражения.
Кристиан О'Рейли
34
Попробуй это:
import math
print[value for value in x ifnot math.isnan(value)]
Для получения дополнительной информации читайте в Списке понятий .
Если вы используете numy, то и мой ответ, и ответ @ lazy1 почти на порядок быстрее, чем понимание списка - решение lazy1 немного быстрее (хотя технически также не будет возвращать значения бесконечности).
Jmetz
Не забывайте скобки :)print ([value for value in x if not math.isnan(value)])
Hyper
Если вы используете numy, как в верхнем ответе, вы можете использовать этот ответ для понимания списка вместе с npпакетом: Итак, возвращает ваш список без nans:[value for value in x if not np.isnan(value)]
yeliabsalohcin
23
Для меня ответ @jmetz не сработал, однако использование pandas isnull () сработало.
Я обнаружил, что сброс к той же самой переменной (x) не удаляет фактические значения nan и должен был использовать другую переменную. Установка его в другую переменную удалила nans. например
Это странно; в соответствии с документами , индексация логического массива (что это такое) находится под расширенной индексацией, которая, по-видимому, «всегда возвращает копию данных», поэтому вы должны xперезаписывать новое значение (т. е. без NaNs ...) , Можете ли вы предоставить больше информации о том, почему это может происходить?
Jmetz
5
Как показали другие
x[~numpy.isnan(x)]
работает. Но он выдаст ошибку, если numpy dtype не является собственным типом данных, например, если это объект. В этом случае вы можете использовать панд.
Общепринятый ответ меняет форму для 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='')
Результат:
====================1DCase:====================Input:[1400.1500.1600. nan nan nan 1700.]
dropna:[1400.1500.1600.1700.]====================2DCase:====================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))]for2D:====================Input:[[1400.1500.1600.][ nan 0. nan][1700.1800. nan]]
dropna:[1400.1500.1600.1700.]
Добро пожаловать на ТАК! Решение, которое вы предлагаете, не отвечает на проблему: ваше решение заменяет NaNs большим числом, в то время как OP попросил полностью удалить элементы.
Пьер Паоло
0
Это мой подход к фильтрации ndarray "X" для NaNs и Infs,
Я создаю карту строк без каких- NaNлибо infследующих действий :
@ jmetz's answer вероятно, тот, который нужен большинству людей; однако он дает одномерный массив, например, делает невозможным удаление целых строк или столбцов в матрицах.
Для этого следует уменьшить логический массив до одного измерения, а затем проиндексировать целевой массив. Например, следующее удалит строки, которые имеют хотя бы одно значение NaN:
Ответы:
Если вы используете NumPy для своих массивов, вы также можете использовать
эквивалентно
[Спасибо chbrown за добавленную стенографию]
объяснение
Внутренняя функция
numpy.isnan
возвращает логический / логический массив, значение которогоTrue
вездеx
не является числом. Поскольку мы хотим обратного, мы используем оператор логического not,~
чтобы получить массив сTrue
s везде, которыйx
является допустимым числом.Наконец, мы используем этот логический массив для индексации в исходном массиве
x
, чтобы получить только значения, отличные от NaN.источник
x = x[numpy.isfinite(x)]
x = x[~numpy.isnan(x)]
, что эквивалентно первоначальному ответу mutzmatron, но короче. Если вы хотите сохранить свою бесконечность, знайтеnumpy.isfinite(numpy.inf) == False
, конечно, но~numpy.isnan(numpy.inf) == True
.np.where(np.isfinite(x), x, 0)
x
не являются массивом. Если вы хотите использовать логический индексирование, он должен быть массив - напримерx = np.array(x)
работает как для списков, так и для массива numpy, поскольку v! = v только для NaN
источник
x
быть указано только один раз, в отличие от решений типаx[~numpy.isnan(x)]
. Это удобно, когдаx
определяется длинным выражением, и вы не хотите загромождать код, создавая временную переменную для хранения результата этого длинного выражения.Попробуй это:
Для получения дополнительной информации читайте в Списке понятий .
источник
print ([value for value in x if not math.isnan(value)])
np
пакетом: Итак, возвращает ваш список без nans:[value for value in x if not np.isnan(value)]
Для меня ответ @jmetz не сработал, однако использование pandas isnull () сработало.
источник
Делаем выше:
или
Я обнаружил, что сброс к той же самой переменной (x) не удаляет фактические значения nan и должен был использовать другую переменную. Установка его в другую переменную удалила nans. например
источник
x
перезаписывать новое значение (т. е. без NaNs ...) , Можете ли вы предоставить больше информации о том, почему это может происходить?Как показали другие
работает. Но он выдаст ошибку, если numpy dtype не является собственным типом данных, например, если это объект. В этом случае вы можете использовать панд.
источник
Общепринятый ответ меняет форму для 2d массивов. Я представляю решение здесь, используя функциональность Pandas dropna () . Работает для 1D и 2D массивов. В 2D-случае вы можете выбрать погоду, чтобы удалить строку или столбец, содержащий
np.nan
.Результат:
источник
Если вы используете
numpy
источник
Самый простой способ это:
Документация: https://docs.scipy.org/doc/numpy/reference/generated/numpy.nan_to_num.html.
источник
NaN
s большим числом, в то время как OP попросил полностью удалить элементы.Это мой подход к фильтрации ndarray "X" для NaNs и Infs,
Я создаю карту строк без каких-
NaN
либоinf
следующих действий :idx - это кортеж Его второй столбец (
idx[1]
) содержит индексы массива, где ни NaN, ни inf не найдены в строке.Затем:
filtered_X
содержит X безNaN
ниinf
.источник
@ jmetz's answer вероятно, тот, который нужен большинству людей; однако он дает одномерный массив, например, делает невозможным удаление целых строк или столбцов в матрицах.
Для этого следует уменьшить логический массив до одного измерения, а затем проиндексировать целевой массив. Например, следующее удалит строки, которые имеют хотя бы одно значение NaN:
Подробнее смотрите здесь .
источник