Як визначити типи numpy в python?


100

Як можна достовірно визначити, чи має об’єкт тип numpy?

Я усвідомлюю, що це питання суперечить філософії набору текстур качок, але ідея полягає у тому, щоб переконатися, що функція (яка використовує scipy та numpy) ніколи не повертає тип numpy, якщо вона не називається з numpy типом. Це підходить до вирішення іншого питання, але я думаю, що загальна проблема визначення того, чи є об'єкт типу numpy, досить далеко від того первісного питання, що їх слід відокремити.


Одне питання: Якщо ви (або, скажімо, scipy) визначаєте тип, який підкласує тип numpy, чи слід це враховувати чи ні? (Я вважаю, що ти не можеш підкласувати типи numpy у Python, але ти можеш у модулі C, і я думаю, ти можеш також підкласувати типи numpypy у PyPy ... так що це, мабуть, не має значення, але це немислимо, що це могло.)
abarnert

Я не думав про це; в основному ваш коментар зазначає, що питання складніше, ніж очікувалося. Чесно кажучи, такий розгляд на високому рівні є надмірним для моєї ситуації. Щодо загальної та портативної відповіді, я б сказав, що поки поведінка визначена, то це нормально.
Дуглас Б. Степл

Відповіді:


116

Використовуйте вбудовану typeфункцію, щоб отримати тип, тоді ви можете використовувати __module__властивість, щоб дізнатися, де вона була визначена:

>>> import numpy as np
a = np.array([1, 2, 3])
>>> type(a)
<type 'numpy.ndarray'>
>>> type(a).__module__
'numpy'
>>> type(a).__module__ == np.__name__
True

наприклад, numpy.ma.MaskedArray недостатньо типу numpy?
panda-34

Якщо ви хочете що-небудь в нумерованому вигляді. * Ви просто пройдете батьківський пакет модуля. (У цей момент ви, очевидно, хочете обернути його у функцію.) І якщо ви хочете, щоб pandas DataFrames вважався numpyish, додайте або, щоб перевірити це. І так далі. Справа в тому, що ви повинні знати, що ви насправді просите, коли хочете зробити щось таке незвичне, як вільне ручне перемикання типу, але, як тільки ви це знаєте, це легко здійснити.
abarnert

1
Це рішення здається дуже непітонічним, спираючись на приховані атрибути. Але, може, це лише питання смаку?
j08lue

2
@ j08lue Вони не є прихованими атрибутами, вони задокументовані спеціальні атрибути. Це все-таки непіфонічно, але я думаю, що це властиво проблемі. (І я думаю, що це сила Python у тому, що коли ти хочеш зробити щось, що перешкоджає мові, найкраще рішення, як правило, є досить потворним, щоб закликати, що ти робиш щось, що зазвичай є поганою ідеєю.)
abarnert

69

Рішення, яке я придумав:

isinstance(y, (np.ndarray, np.generic) )

Однак не на 100% зрозуміло, що всі типи нумеру гарантовано є np.ndarrayабо np.generic, і це, мабуть, не є надійною версією.


1
Я припускаю, що ви можете фільтрувати dir(numpy)типи та вбудовані функції (і класи, але я не думаю, що вони є) і використовувати це для створення кортежу isinstanceпроти, який був би надійним. (Я вважаю, що ви можете передати вбудовані функції isinstance, чи є вони насправді конструкторами типу чи ні, але вам доведеться це перевірити.)
abarnert

Так, усі вони повинні бути підкласами цих двох AFAIK.
seberg

@seberg Дякую. На даний момент це, звичайно, так, але документація python не дуже зрозуміла щодо цього, і це могло б змінитися в майбутньому.
Дуглас Б. Степл

19

Старе питання, але я запропонував остаточну відповідь із прикладом. Не зашкодить підтримувати свіжі питання, оскільки у мене була така сама проблема і я не знайшов чіткої відповіді. Головне - переконатися, що ви numpyімпортували, а потім запустити isinstancebool. Хоча це може здатися простим, якщо ви виконуєте деякі обчислення для різних типів даних, ця невелика перевірка може послужити швидким тестом перед початком певної операції з векторизацією numpy.

##################
# important part!
##################

import numpy as np

####################
# toy array for demo
####################

arr = np.asarray(range(1,100,2))

########################
# The instance check
######################## 

isinstance(arr,np.ndarray)

9

Це насправді залежить від того, що ви шукаєте.

  • Якщо ви хочете перевірити, чи послідовність насправді є ndarraya isinstance(..., np.ndarray), мабуть, найпростіша. Переконайтеся, що ви не перезавантажуєте numpy у фоновому режимі, оскільки модуль може бути іншим, але в іншому випадку з вами повинно бути все в порядку. MaskedArrays, matrix, recarrayВсе підкласиndarray , так що ви повинні бути встановлені.
  • Якщо ви хочете перевірити, чи не є скаляр скалярним нулем, все стає дещо складнішим. Ви можете перевірити, чи є в shapeньому dtypeатрибут. Ви можете порівняти його dtypeз основними типами d-типів, список яких ви можете знайти в np.core.numerictypes.genericTypeRank. Зверніть увагу, що елементи цього списку є рядками, тому вам доведеться зробити tested.dtype is np.dtype(an_element_of_the_list)...

+1. Якщо ви насправді шукаєте щось, крім "це numpyтип", і можете визначити, що це таке, це краще, ніж інші відповіді. І в більшості випадків вам слід шукати щось конкретне, що ви можете визначити.
abarnert

8

Щоб отримати тип, використовуйте вбудовану typeфункцію. За допомогою inоператора ви можете перевірити, чи тип є типом numpy, перевіривши, чи містить він рядок numpy;

In [1]: import numpy as np

In [2]: a = np.array([1, 2, 3])

In [3]: type(a)
Out[3]: <type 'numpy.ndarray'>

In [4]: 'numpy' in str(type(a))
Out[4]: True

(Цей приклад , до речі, був запущений в IPython . Дуже зручний для інтерактивного використання та швидких тестів.)


2
Це працює, але якщо ви визначите тип, який називається, скажімо, "numpygroup", ви отримаєте помилкові спрацьовування. Крім того, залежно від рядкового представлення типів - погана ідея, якщо ви можете цього уникнути - і в цьому випадку ви можете. Подивіться на його модуль.
abarnert

Використання модуля справді є кращим рішенням.
Роланд Сміт

Може використовуватися регулярний
вираз

@ Omkaar.K Regex для чого можна використовувати? Зробити ту саму перевірку дещо складнішим способом?
abarnert

@abamert "Не міг" - це те, що я сказав, також регулярний вираз може виглядати складним для таких простих завдань, як ці, але це надзвичайно корисно для великих завдань обробки рядків, тому навчитися цьому не дуже. Я думаю, ви знаєте, що вже з того часу, як ваш портфель зображує вас як старшого програміста?
omkaartg

3

Зауважте, що type(numpy.ndarray)це typeсамо по собі і стежте за булевими та скалярними типами. Не будьте занадто розгублені, якщо це не інтуїтивно чи просто, спочатку це біль.

Див. Також: - https://docs.scipy.org/doc/numpy-1.15.1/reference/arrays.dtypes.html - https://github.com/machinalis/mypy-data/tree/master/numpy- міпі

>>> import numpy as np
>>> np.ndarray
<class 'numpy.ndarray'>
>>> type(np.ndarray)
<class 'type'>
>>> a = np.linspace(1,25)
>>> type(a)
<class 'numpy.ndarray'>
>>> type(a) == type(np.ndarray)
False
>>> type(a) == np.ndarray
True
>>> isinstance(a, np.ndarray)
True

Розваги з булею:

>>> b = a.astype('int32') == 11
>>> b[0]
False
>>> isinstance(b[0], bool)
False
>>> isinstance(b[0], np.bool)
False
>>> isinstance(b[0], np.bool_)
True
>>> isinstance(b[0], np.bool8)
True
>>> b[0].dtype == np.bool
True
>>> b[0].dtype == bool  # python equivalent
True

Більше розваг зі скалярними типами, див .: https://docs.scipy.org/doc/numpy-1.15.1/reference/arrays.scalars.html#arrays-scalars-built-in

>>> x = np.array([1,], dtype=np.uint64)
>>> x[0].dtype
dtype('uint64')
>>> isinstance(x[0], np.uint64)
True
>>> isinstance(x[0], np.integer)
True  # generic integer
>>> isinstance(x[0], int)
False  # but not a python int in this case

# Try matching the `kind` strings, e.g.
>>> np.dtype('bool').kind                                                                                           
'b'
>>> np.dtype('int64').kind                                                                                          
'i'
>>> np.dtype('float').kind                                                                                          
'f'
>>> np.dtype('half').kind                                                                                           
'f'

# But be weary of matching dtypes
>>> np.integer
<class 'numpy.integer'>
>>> np.dtype(np.integer)
dtype('int64')
>>> x[0].dtype == np.dtype(np.integer)
False

# Down these paths there be dragons:

# the .dtype attribute returns a kind of dtype, not a specific dtype
>>> isinstance(x[0].dtype, np.dtype)
True
>>> isinstance(x[0].dtype, np.uint64)
False  
>>> isinstance(x[0].dtype, np.dtype(np.uint64))
Traceback (most recent call last):
  File "<console>", line 1, in <module>
TypeError: isinstance() arg 2 must be a type or tuple of types
# yea, don't go there
>>> isinstance(x[0].dtype, np.int_)
False  # again, confusing the .dtype with a specific dtype


# Inequalities can be tricky, although they might
# work sometimes, try to avoid these idioms:

>>> x[0].dtype <= np.dtype(np.uint64)
True
>>> x[0].dtype <= np.dtype(np.float)
True
>>> x[0].dtype <= np.dtype(np.half)
False  # just when things were going well
>>> x[0].dtype <= np.dtype(np.float16)
False  # oh boy
>>> x[0].dtype == np.int
False  # ya, no luck here either
>>> x[0].dtype == np.int_
False  # or here
>>> x[0].dtype == np.uint64
True  # have to end on a good note!
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.