Идентификация числовых и массивных типов в numpy - PullRequest
14 голосов
/ 01 февраля 2009

Существует ли существующая функция в numpy, которая сообщит мне, является ли значение числовым типом или массивом numpy? Я пишу некоторый код обработки данных, который должен обрабатывать числа в нескольких различных представлениях (под «числом» я подразумеваю любое представление числовой величины, которой можно манипулировать с помощью стандартных арифметических операторов, +, -, *, /, * *).

Некоторые примеры поведения, которое я ищу

>>> is_numeric(5)
True
>>> is_numeric(123.345)
True
>>> is_numeric('123.345')
False
>>> is_numeric(decimal.Decimal('123.345'))
True
>>> is_numeric(True)
False
>>> is_numeric([1, 2, 3])
False
>>> is_numeric([1, '2', 3])
False
>>> a = numpy.array([1, 2.3, 4.5, 6.7, 8.9])
>>> is_numeric(a)
True
>>> is_numeric(a[0])
True
>>> is_numeric(a[1])
True
>>> is_numeric(numpy.array([numpy.array([1]), numpy.array([2])])
True
>>> is_numeric(numpy.array(['1'])
False

Если такой функции не существует, я знаю, что написать ее не сложно, что-то вроде

isinstance(n, (int, float, decimal.Decimal, numpy.number, numpy.ndarray))

но есть ли другие числовые типы, которые я должен включить в список?

Ответы [ 5 ]

18 голосов
/ 01 февраля 2009

Как уже отвечали другие, могут быть и другие числовые типы, кроме тех, которые вы упомянули. Один из подходов заключается в явной проверке нужных вам возможностей, например,

# Python 2
def is_numeric(obj):
    attrs = ['__add__', '__sub__', '__mul__', '__div__', '__pow__']
    return all(hasattr(obj, attr) for attr in attrs)

# Python 3
def is_numeric(obj):
    attrs = ['__add__', '__sub__', '__mul__', '__truediv__', '__pow__']
    return all(hasattr(obj, attr) for attr in attrs)

Это работает для всех ваших примеров, кроме последнего, numpy.array(['1']). Это потому, что numpy.ndarray имеет специальные методы для числовых операций, но вызывает TypeError, если вы пытаетесь использовать их ненадлежащим образом для строковых или объектных массивов. Вы можете добавить явную проверку для этого как

 ... and not (isinstance(obj, ndarray) and obj.dtype.kind in 'OSU')

Это может быть достаточно хорошо.

Но ... вы никогда не сможете быть 100% уверенными в том, что кто-то не определит другой тип с таким же поведением, поэтому более надежный способ - на самом деле попытаться выполнить вычисление и поймать исключение что-то вроде

def is_numeric_paranoid(obj):
    try:
        obj+obj, obj-obj, obj*obj, obj**obj, obj/obj
    except ZeroDivisionError:
        return True
    except Exception:
        return False
    else:
        return True

но в зависимости от того, как часто вы планируете звонить, используйте его и с какими аргументами, это может быть непрактично (может быть медленным, например, с большими массивами).

5 голосов
/ 01 февраля 2009

В общем, гибкий, быстрый и pythonic способ обработки неизвестных типов состоит в том, чтобы просто выполнить некоторую операцию с ними и перехватить исключение для недопустимых типов.

try:
    a = 5+'5'
except TypeError:
    print "Oops"

Мне кажется, что такой подход проще, чем специальное выделение какой-либо функции для определения абсолютной достоверности типа.

4 голосов
/ 21 января 2010

Кроме того, numpy имеет numpy.isreal и другие подобные функции (numpy.is + Tab должен перечислять их).

У всех есть свои забавные угловые чехлы, но один из них может быть полезен.

0 голосов
/ 20 января 2010

isinstance(numpy.int32(4), numbers.Number) возвращает False, так что это не совсем работает. operator.isNumberType() действительно работает на всех вариантах чисел numpy, включая numpy.array([1]).

0 голосов
/ 01 февраля 2009

Ваш is_numeric плохо определен. Смотрите мои комментарии к вашему вопросу.

Другие числовые типы могут быть: long, complex, fractions.Fraction, numpy.bool_, numpy.ubyte, ...

operator.isNumberType() возвращает True для номеров Python и numpy.array.

Начиная с Python 2.6, вы можете использовать isinstance(d, numbers.Number) вместо устаревшего operator.isNumberType().

Как правило, лучше проверить возможности объекта (например, можете ли вы добавить к нему целое число), а не его тип.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...