Я работаю с массивами numpy разных типов данных. Я хотел бы знать, какого-либо определенного массива, элементами которого являются NaN. Обычно это то, за чем стоит np.isnan
.np.isnan на массивах dtype "object"
Однако np.isnan
не дружит с массивами типа данных object
(или любой другой тип данных строки):
>>> str_arr = np.array(["A", "B", "C"])
>>> np.isnan(str_arr)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Not implemented for this type
>>> obj_arr = np.array([1, 2, "A"], dtype=object)
>>> np.isnan(obj_arr)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: ufunc 'isnan' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe''
То, что я хотел бы выйти из этих двух вызовов просто np.array([False, False, False])
. Я не могу просто поставить try
и except TypeError
вокруг моего звонка на np.isnan
и предположить, что любой массив, который генерирует TypeError
, не содержит NaN: в конце концов, мне бы хотелось, чтобы np.isnan(np.array([1, np.NaN, "A"]))
вернулся np.array([False, True, False])
.
Мое текущее решение состоит в том, чтобы создать новый массив типа np.float64
, пропустить элементы исходного массива, try
ing, чтобы поместить этот элемент в новый массив (и если он не сработает, оставьте его как ноль), а затем вызвав np.isnan
на новый массив. Однако это, конечно, довольно медленно. (По крайней мере, для больших массивов объектов.)
def isnan(arr):
if isinstance(arr, np.ndarray) and (arr.dtype == object):
# Create a new array of dtype float64, fill it with the same values as the input array (where possible), and
# then call np.isnan on the new array. This way, np.isnan is only called once. (Much faster than calling it on
# every element in the input array.)
new_arr = np.zeros((len(arr),), dtype=np.float64)
for idx in xrange(len(arr)):
try:
new_arr[idx] = arr[idx]
except Exception:
pass
return np.isnan(new_arr)
else:
try:
return np.isnan(arr)
except TypeError:
return False
Эта конкретная реализация также работает только для одномерных массивов, и я не могу думать о приличном образом, чтобы запустить в for
петлю над произвольным числом Габаритные размеры.
Есть ли более эффективный способ выяснить, какие элементы в массиве являются NaN?
EDIT: Я запускаю Python 2.7.10.
Отметьте, что [x is np.nan for x in np.array([np.nan])]
возвращает False
: np.nan
не всегда тот же объект в памяти, что и другой np.nan
.
Я не хочу строку"nan"
будет считаться эквивалентной np.nan
: Я хочу isnan(np.array(["nan"], dtype=object))
вернуться np.array([False])
.
Многомерность не является большой проблемой. (Ничего, что немного ravel
-и- reshape
ИНГ не исправит: стр.)
Любая функция, которая зависит от оператора is
для проверки эквивалентности двух NaNs не всегда будет работать. (Если вы думаете, что должны, спросите себя, что делает оператор is
!)
Я бы попробовать «небезопасный» принуждение копию, хотя я не то, что строки будут endup как. Возможно, вам придется расколоться или сгладить. – hpaulj
@hpaulj Не могли бы вы расширить свое предложение? Я не следую тому, что вы предлагаете. – acdr