Làm thế nào để xác định các loại numpy trong trăn?


100

Làm thế nào người ta có thể xác định một cách đáng tin cậy nếu một đối tượng có kiểu numpy?

Tôi nhận ra rằng câu hỏi này đi ngược lại triết lý của kiểu gõ vịt, nhưng ý tưởng là đảm bảo một hàm (sử dụng scipy và numpy) không bao giờ trả về kiểu numpy trừ khi nó được gọi với kiểu numpy. Điều này đưa ra giải pháp cho một câu hỏi khác, nhưng tôi nghĩ rằng vấn đề chung của việc xác định xem một đối tượng có kiểu numpy đủ xa với câu hỏi ban đầu để chúng nên được tách biệt.


Một câu hỏi: Nếu bạn (hoặc, giả sử, scipy) xác định một kiểu phân lớp một kiểu numpy, thì kiểu đó có được tính hay không? (Tôi tin rằng bạn không thể phân lớp các kiểu numpy trong Python, nhưng bạn có thể trong mô-đun C và tôi nghĩ rằng bạn cũng có thể phân lớp các kiểu numpypy của lớp con trong PyPy… vì vậy có thể không thành vấn đề, nhưng điều đó không thể tưởng tượng được.)
abarnert

Tôi đã không nghĩ về điều đó; về cơ bản nhận xét của bạn chỉ ra rằng câu hỏi khó hơn mong đợi. Thành thật mà nói, loại cân nhắc cấp cao là quá mức cần thiết cho tình huống của tôi. Đối với câu trả lời chung và di động, tôi sẽ nói rằng miễn là hành vi được xác định thì nó được.
Douglas B. Staple

Câu trả lời:


116

Sử dụng typehàm nội trang để lấy kiểu, sau đó bạn có thể sử dụng thuộc __module__tính để tìm ra nơi nó được xác định:

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

ví dụ: numpy.ma.MaskedArray không phải là loại đủ numpy?
panda-34,

Nếu bạn muốn bất cứ thứ gì trong numpy. * Bạn chỉ cần đi bộ gói cha của mô-đun. (Tại thời điểm đó, bạn rõ ràng muốn gói nó trong một hàm.) Và nếu bạn muốn DataFrames gấu trúc được tính là numpyish, hãy thêm một hoặc để kiểm tra điều đó. Và như thế. Vấn đề là, bạn phải biết những gì bạn thực sự yêu cầu khi bạn muốn làm điều gì đó bất thường như chuyển đổi kiểu thủ công lỏng lẻo, nhưng một khi bạn biết, bạn sẽ dễ dàng thực hiện.
abarnert

1
Giải pháp này có vẻ rất đơn giản, dựa trên các thuộc tính ẩn. Nhưng có lẽ đó chỉ là vấn đề thị hiếu?
j08lue

2
@ j08lue Chúng không phải là các thuộc tính ẩn, chúng là các thuộc tính đặc biệt được ghi lại. Tuy nhiên, nó không hề phức tạp, nhưng tôi nghĩ đó là vấn đề cố hữu. (Và tôi nghĩ đó là một sức mạnh của Python rằng khi bạn muốn làm một cái gì đó là không khuyến khích ngôn ngữ, giải pháp tốt nhất thường là đủ rõ ràng xấu xí để gọi ra rằng bạn đang làm một cái gì đó thường là một ý tưởng tồi.)
abarnert

69

Giải pháp tôi đã đưa ra là:

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

Tuy nhiên, không rõ ràng 100% rằng tất cả các loại numpy đều được đảm bảo np.ndarrayhoặc np.genericvà đây có thể không phải là phiên bản mạnh mẽ.


1
Tôi cho rằng bạn có thể lọc dir(numpy)các loại và hàm nội trang (và các lớp, nhưng tôi không nghĩ nó có bất kỳ) và sử dụng nó để tạo một bộ tuple để isinstancechống lại, điều này sẽ rất mạnh mẽ. (Tôi tin rằng bạn có thể vượt qua được xây dựng trong chức năng để isinstance cho dù họ đang thực sự gõ nhà xây dựng hay không, nhưng bạn sẽ phải kiểm tra xem.)
abarnert

Đúng, tất cả chúng phải là lớp con của hai AFAIK đó.
seberg

@seberg Cảm ơn. Hiện tại có vẻ là đúng như vậy, nhưng tài liệu về python không rõ ràng lắm về điều này và nó có thể thay đổi trong tương lai.
Douglas B. Staple

19

Câu hỏi cũ nhưng tôi đã đưa ra một câu trả lời dứt khoát với một ví dụ. Thật khó để giữ cho các câu hỏi luôn mới vì tôi đã gặp vấn đề tương tự và không tìm thấy câu trả lời rõ ràng. Điều quan trọng là đảm bảo rằng bạn đã numpynhập và sau đó chạy isinstancebool. Mặc dù điều này có vẻ đơn giản, nhưng nếu bạn đang thực hiện một số tính toán trên các loại dữ liệu khác nhau, kiểm tra nhỏ này có thể dùng như một bài kiểm tra nhanh trước khi bạn bắt đầu một số thao tác vectơ phức tạp.

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

Điều đó thực sự phụ thuộc vào những gì bạn đang tìm kiếm.

  • Nếu bạn muốn kiểm tra xem một chuỗi có thực sự là a hay không ndarray, a isinstance(..., np.ndarray)có lẽ là cách dễ nhất. Đảm bảo rằng bạn không tải lại numpy trong nền vì mô-đun có thể khác, nhưng nếu không, bạn sẽ ổn. MaskedArrays, matrix, recarrayĐều là lớp con của ndarray, vì vậy bạn nên được thiết lập.
  • Nếu bạn muốn kiểm tra xem một đại lượng vô hướng có phải là một đại lượng vô hướng không, mọi thứ sẽ phức tạp hơn một chút. Bạn có thể kiểm tra xem nó có một shapevà một dtypethuộc tính. Bạn có thể so sánh nó dtypevới các kiểu cơ bản, có danh sách mà bạn có thể tìm thấy np.core.numerictypes.genericTypeRank. Lưu ý rằng các phần tử của danh sách này là các chuỗi, vì vậy bạn phải thực hiện tested.dtype is np.dtype(an_element_of_the_list)...

+1. Nếu bạn thực sự đang tìm kiếm thứ gì đó ngoài "là một numpyloại" và có thể xác định thứ đó là gì, thì câu trả lời này tốt hơn các câu trả lời khác. Và trong hầu hết các trường hợp, bạn nên tìm kiếm một cái gì đó cụ thể mà bạn có thể xác định.
abarnert 24/09/12

8

Để lấy loại, hãy sử dụng typehàm nội trang . Với intoán tử, bạn có thể kiểm tra xem kiểu có phải là kiểu numpy không bằng cách kiểm tra xem nó có chứa chuỗi hay không 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

(Nhân tiện, ví dụ này đã được chạy trong IPython . Rất tiện dụng để sử dụng tương tác và kiểm tra nhanh.)


2
Điều này hoạt động, nhưng nếu bạn xác định một loại được gọi là "numpygroup", bạn sẽ nhận được kết quả dương tính giả. Ngoài ra, tùy thuộc vào biểu diễn chuỗi của các loại là một ý tưởng tồi nếu bạn có thể tránh nó — và trong trường hợp này, bạn có thể. Thay vào đó, hãy nhìn vào mô-đun của nó.
abarnert 24/09/12

Sử dụng mô-đun thực sự là một giải pháp tốt hơn.
Roland Smith,

Regex có thể được sử dụng
omkaartg

@ Omkaar.K Regex có thể được sử dụng để làm gì? Để thực hiện việc kiểm tra chính xác tương tự theo cách phức tạp hơn một chút?
abarnert

@abamert "Có thể" là những gì tôi đã nói, regex cũng có thể trông phức tạp đối với các tác vụ đơn giản như thế này, nhưng nó cực kỳ hữu ích cho các tác vụ xử lý chuỗi lớn, vì vậy không phải là một ý tưởng tồi để tìm hiểu nó. Tôi đoán bạn đã biết điều đó vì danh mục đầu tư của bạn mô tả bạn là một lập trình viên cao cấp?
omkaartg

3

Lưu ý rằng chính type(numpy.ndarray)là một typevà chú ý đến các kiểu boolean và vô hướng. Đừng quá nản lòng nếu nó không trực quan hoặc dễ dàng, đó là một nỗi đau đầu tiên.

Xem thêm: - 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

Vui vẻ với 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

Thú vị hơn với các loại vô hướng, hãy xem: - 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!
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.