Bagaimana cara mengidentifikasi tipe numpy di python?

100

Bagaimana seseorang dapat dengan andal menentukan apakah suatu objek memiliki tipe numpy?

Saya menyadari bahwa pertanyaan ini bertentangan dengan filosofi mengetik bebek, tetapi idenya adalah untuk memastikan suatu fungsi (yang menggunakan scipy dan numpy) tidak pernah mengembalikan tipe numpy kecuali jika dipanggil dengan tipe numpy. Ini muncul dalam solusi untuk pertanyaan lain, tetapi saya pikir masalah umum untuk menentukan apakah suatu objek memiliki tipe numpy cukup jauh dari pertanyaan awal sehingga mereka harus dipisahkan.

Douglas B. Staple
sumber
Satu pertanyaan: Jika Anda (atau, katakanlah, scipy) mendefinisikan tipe yang membuat subclass tipe numpy, haruskah itu dihitung atau tidak? (Saya yakin Anda tidak bisa membuat subkelas tipe numpy dengan Python, tetapi Anda bisa dalam modul C, dan saya rasa Anda juga bisa membuat subkelas tipe numpypy di PyPy… jadi mungkin tidak masalah, tapi tidak terbayangkan bahwa itu bisa.)
abarnert
Saya tidak memikirkan itu; pada dasarnya komentar Anda menunjukkan bahwa pertanyaan itu lebih sulit dari yang diharapkan. Jujur saja, pertimbangan tingkat tinggi semacam itu terlalu berlebihan untuk situasi saya. Untuk jawaban umum dan portabel, saya akan mengatakan bahwa selama perilaku didefinisikan maka tidak apa-apa.
Douglas B. Staple

Jawaban:

116

Gunakan typefungsi bawaan untuk mendapatkan tipe, lalu Anda dapat menggunakan __module__properti untuk mencari tahu di mana ia didefinisikan:

>>> 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
abarnert
sumber
apakah misalnya numpy.ma.MaskedArray bukan tipe yang cukup numpy?
panda-34
Jika Anda menginginkan sesuatu di numpy. * Anda cukup menjalankan paket induk dari modul. (Pada titik itu, Anda jelas ingin membungkusnya dalam sebuah fungsi.) Dan jika Anda ingin pandas DataFrames dihitung sebagai numpyish, tambahkan atau untuk mengujinya. Dan seterusnya. Intinya adalah, Anda harus tahu apa yang sebenarnya Anda minta ketika Anda ingin melakukan sesuatu yang tidak biasa seperti peralihan tipe manual yang longgar, tetapi begitu Anda tahu, itu mudah untuk diterapkan.
abarnert
1
Solusi ini nampaknya sangat unpythonic, mengandalkan atribut tersembunyi. Tapi mungkinkah itu hanya masalah selera?
j08lue
2
@ j08lue Itu bukan atribut tersembunyi, itu adalah atribut khusus yang didokumentasikan. Ini, bagaimanapun, unpythonic, tapi saya pikir itu melekat pada masalahnya. (Dan saya pikir itu adalah kekuatan Python bahwa ketika Anda ingin melakukan sesuatu yang bahasa tidak mendukung, solusi terbaik biasanya terlihat cukup jelek untuk menyatakan bahwa Anda melakukan sesuatu yang biasanya ide yang buruk.)
abarnert
69

Solusi yang saya dapatkan adalah:

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

Namun, tidak 100% jelas bahwa semua jenis numpy dijamin salah satu np.ndarrayatau np.generic, dan ini mungkin bukan versi yang kuat.

Douglas B. Staple
sumber
1
Saya kira Anda dapat memfilter dir(numpy)jenis dan fungsi bawaan (dan kelas, tapi saya rasa tidak ada) dan menggunakannya untuk menghasilkan tupel untuk isinstancemelawan, yang akan menjadi kuat. (Saya yakin Anda dapat meneruskan fungsi bawaan ke isinstance apakah mereka benar-benar tipe konstruktor atau tidak, tetapi Anda harus memeriksanya.)
abarnert
Ya, mereka semua harus menjadi subclass dari dua AFAIK tersebut.
seberg
@eberg Terima kasih. Tampaknya memang demikian untuk saat ini, tetapi dokumentasi python tidak terlalu jelas tentang hal ini dan dapat berubah di masa depan.
Douglas B. Staple
19

Pertanyaan lama tetapi saya mendapatkan jawaban pasti dengan sebuah contoh. Tidak ada salahnya untuk menjaga pertanyaan tetap segar karena saya memiliki masalah yang sama dan tidak menemukan jawaban yang jelas. Kuncinya adalah memastikan Anda telah numpymengimpor, lalu menjalankan isinstancebool. Meskipun ini mungkin tampak sederhana, jika Anda melakukan beberapa komputasi di berbagai tipe data, pemeriksaan kecil ini dapat berfungsi sebagai pengujian cepat sebelum Anda memulai beberapa operasi vektorisasi 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)
Linwoodc3
sumber
9

Itu sebenarnya tergantung pada apa yang Anda cari.

  • Jika Anda ingin menguji apakah suatu urutan sebenarnya adalah a ndarray, a isinstance(..., np.ndarray)mungkin adalah yang termudah. Pastikan Anda tidak memuat ulang numpy di latar belakang karena modulnya mungkin berbeda, tetapi sebaliknya, Anda akan baik-baik saja. MaskedArrays, matrix, recarraySemua subclass dari ndarray, sehingga Anda harus ditetapkan.
  • Jika Anda ingin menguji apakah skalar adalah skalar numpy, segalanya menjadi sedikit lebih rumit. Anda dapat memeriksa apakah itu memiliki shapedan dtypeatribut. Anda dapat membandingkannya dengan dtypedtypes dasar, yang daftarnya dapat Anda temukan di np.core.numerictypes.genericTypeRank. Perhatikan bahwa elemen dari daftar ini adalah string, jadi Anda harus melakukan tested.dtype is np.dtype(an_element_of_the_list)...
Pierre GM
sumber
+1. Jika Anda benar-benar mencari sesuatu selain "adalah numpytipe", dan dapat mendefinisikan apa itu sesuatu, ini lebih baik daripada jawaban lainnya. Dan dalam banyak kasus, Anda harus mencari sesuatu yang spesifik yang dapat Anda definisikan.
abarnert
8

Untuk mendapatkan tipenya, gunakan typefungsi builtin . Dengan inoperator, Anda dapat menguji apakah tipe tersebut adalah tipe numpy dengan memeriksa apakah itu berisi string 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

(Contoh ini dijalankan di IPython . Sangat berguna untuk penggunaan interaktif dan tes cepat.)

Roland Smith
sumber
2
Ini berfungsi, tetapi jika Anda menentukan jenis yang disebut, katakanlah, "numpygroup", Anda akan mendapatkan positif palsu. Selain itu, bergantung pada representasi string dari tipe adalah ide yang buruk jika Anda bisa menghindarinya — dan dalam kasus ini, Anda bisa. Lihat modulnya sebagai gantinya.
abarnert
Menggunakan modul memang merupakan solusi yang lebih baik.
Roland Smith
Regex dapat digunakan
omkaartg
@ Omkaar.K Regex bisa digunakan untuk apa? Untuk melakukan pemeriksaan yang sama persis dengan cara yang sedikit lebih rumit?
Abarnert
@abamert "Could" adalah apa yang saya katakan, juga regex bisa terlihat rumit untuk tugas sederhana seperti ini, tetapi sangat berguna untuk tugas pemrosesan string besar, Jadi bukan ide yang buruk untuk mempelajarinya. Saya rasa Anda sudah tahu bahwa sejak portofolio Anda menggambarkan Anda sebagai programmer senior?
omkaartg
3

Perhatikan bahwa type(numpy.ndarray)is a typeitu sendiri dan hati-hati terhadap jenis boolean dan skalar. Jangan terlalu putus asa jika tidak intuitif atau mudah, ini menyakitkan pada awalnya.

Lihat juga: - https://docs.scipy.org/doc/numpy-1.15.1/reference/arrays.dtypes.html - https://github.com/machinalis/mypy-data/tree/master/numpy- mypy

>>> 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

Bersenang-senang dengan boolean:

>>> 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

Lebih asyik dengan jenis skalar, lihat: - 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!
Darren Weber
sumber