วิธีระบุประเภท numpy ใน python


101

เราจะตรวจสอบได้อย่างไรว่าวัตถุมีประเภทตัวเลขหรือไม่?

ฉันตระหนักดีว่าคำถามนี้ขัดกับหลักปรัชญาของการพิมพ์แบบเป็ด แต่ความคิดคือเพื่อให้แน่ใจว่าฟังก์ชัน (ซึ่งใช้ scipy และ numpy) จะไม่ส่งคืนประเภท numpy เว้นแต่จะเรียกด้วยประเภทที่เป็นตัวเลข สิ่งนี้เกิดขึ้นในการแก้ปัญหาสำหรับคำถามอื่นแต่ฉันคิดว่าปัญหาทั่วไปในการพิจารณาว่าวัตถุมีประเภทตัวเลขอยู่ห่างจากคำถามเดิมมากพอที่จะแยกออกจากกันได้หรือไม่


คำถามหนึ่ง: หากคุณ (หรือพูดว่า scipy) กำหนดประเภทที่ย่อยเป็นประเภท numpy ควรนับหรือไม่? (ฉันเชื่อว่าคุณไม่สามารถ subclass ประเภท numpy ใน Python ได้ แต่คุณสามารถทำได้ในโมดูล C และฉันคิดว่าคุณสามารถ subclass ประเภท numpypy ใน PyPy ได้ ... ดังนั้นมันอาจจะไม่สำคัญ แต่ก็ไม่น่าเชื่อว่าจะทำได้)
ยกเลิก

ฉันไม่ได้คิดอย่างนั้น โดยพื้นฐานแล้วความคิดเห็นของคุณชี้ให้เห็นว่าคำถามนั้นยากกว่าที่คิด จริงๆแล้วการพิจารณาระดับสูงแบบนั้นเป็นวิธีที่มากเกินไปสำหรับสถานการณ์ของฉัน สำหรับคำตอบทั่วไปและแบบพกพาฉันจะบอกว่าตราบใดที่มีการกำหนดพฤติกรรมก็โอเค
Douglas B.Staple

คำตอบ:


117

ใช้typeฟังก์ชันbuiltin เพื่อรับประเภทจากนั้นคุณสามารถใช้__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 เป็นประเภทที่ไม่เพียงพอหรือไม่
panda-34

หากคุณต้องการอะไรที่เป็นตัวเลข * คุณเพียงแค่เดินไปตามแพ็คเกจหลักของโมดูล (ณ จุดนั้นคุณต้องการรวมมันไว้ในฟังก์ชัน) และถ้าคุณต้องการให้แพนด้า DataFrames นับเป็นตัวเลขให้เพิ่มหรือเพื่อทดสอบสิ่งนั้น และอื่น ๆ ประเด็นคือคุณต้องรู้ว่าคุณต้องการอะไรเมื่อคุณต้องการทำสิ่งที่ผิดปกติเช่นเดียวกับการสลับประเภทด้วยตนเองแบบหลวม ๆ แต่เมื่อคุณรู้แล้วก็ง่ายต่อการใช้งาน
ยกเลิก

1
วิธีการแก้ปัญหานี้ดูไม่น่ากลัวมากโดยอาศัยคุณลักษณะที่ซ่อนอยู่ แต่นั่นอาจเป็นเพียงเรื่องของรสนิยม?
j08lue

2
@ j08lue ไม่ใช่แอตทริบิวต์ที่ซ่อนอยู่ แต่มีการบันทึกคุณลักษณะพิเศษไว้ อย่างไรก็ตามมันเป็นเรื่องที่ไม่น่าเชื่อ แต่ฉันคิดว่ามันมีอยู่ในปัญหา (และฉันคิดว่ามันเป็นจุดแข็งของ Python ที่เมื่อคุณต้องการทำบางสิ่งบางอย่างที่ภาษาไม่
เอื้ออำนวย

73

วิธีแก้ปัญหาที่ฉันคิดขึ้นคือ:

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

อย่างไรก็ตามยังไม่ชัดเจน 100%ว่าประเภท numpy ทั้งหมดได้รับการรับรองว่าเป็นnp.ndarrayหรือnp.genericและอาจไม่ใช่เวอร์ชันที่มีประสิทธิภาพ


1
ฉันคิดว่าคุณสามารถกรองdir(numpy)ประเภทและฟังก์ชันในตัว (และคลาส แต่ฉันไม่คิดว่ามันมี) และใช้สิ่งนั้นเพื่อสร้างทูเพิลเพื่อisinstanceต่อต้านซึ่งจะมีประสิทธิภาพ (ฉันเชื่อว่าคุณสามารถส่งผ่านฟังก์ชัน builtin ไปยัง isinstance ได้ไม่ว่าพวกเขาจะพิมพ์ constructor จริงหรือไม่ แต่คุณต้องตรวจสอบ)
ยกเลิก

ใช่พวกเขาทั้งหมดควรเป็นคลาสย่อยของ AFAIK สองคนนั้น
seberg

@seberg ขอบคุณ ดูเหมือนว่าจะเป็นเช่นนั้นในตอนนี้ แต่เอกสารเกี่ยวกับ python ยังไม่ชัดเจนในเรื่องนี้และอาจมีการเปลี่ยนแปลงในอนาคต
Douglas B.Staple

20

คำถามเก่า แต่ฉันได้คำตอบที่ชัดเจนพร้อมตัวอย่าง ไม่สามารถเจ็บใจที่จะตั้งคำถามให้สดใหม่เพราะฉันมีปัญหาเดียวกันนี้และไม่พบคำตอบที่ชัดเจน กุญแจสำคัญคือตรวจสอบให้แน่ใจว่าคุณได้numpyนำเข้าจากนั้นเรียกใช้isinstanceบูล แม้ว่าสิ่งนี้อาจดูเรียบง่าย แต่หากคุณทำการคำนวณในประเภทข้อมูลต่างๆการตรวจสอบขนาดเล็กนี้สามารถใช้เป็นการทดสอบอย่างรวดเร็วก่อนที่คุณจะเริ่มการดำเนินการที่เป็นเวกเตอร์ที่เป็นตัวเลข

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

ขึ้นอยู่กับสิ่งที่คุณกำลังมองหา

  • ถ้าคุณต้องการทดสอบว่าลำดับเป็น a จริงndarrayหรือไม่ a isinstance(..., np.ndarray)น่าจะง่ายที่สุด ตรวจสอบให้แน่ใจว่าคุณไม่ได้โหลด numpy ซ้ำในพื้นหลังเนื่องจากโมดูลอาจแตกต่างกัน แต่อย่างอื่นคุณควรจะโอเค MaskedArrays, matrix, recarrayมี subclasses ทั้งหมดndarrayดังนั้นคุณควรจะตั้งค่า
  • หากคุณต้องการทดสอบว่าสเกลาร์เป็นสเกลาร์ตัวเลขหรือไม่สิ่งต่างๆจะซับซ้อนขึ้นเล็กน้อย คุณสามารถตรวจสอบได้ว่ามีshapeและdtypeแอตทริบิวต์หรือไม่ คุณสามารถเปรียบเทียบdtypeกับ dtypes พื้นฐานซึ่งมีรายการที่คุณสามารถค้นหาnp.core.numerictypes.genericTypeRankได้ โปรดทราบว่าองค์ประกอบของรายการนี้เป็นสตริงดังนั้นคุณต้องทำtested.dtype is np.dtype(an_element_of_the_list)...

+1. หากคุณกำลังมองหาบางสิ่งที่นอกเหนือจาก "เป็นnumpyประเภท" และสามารถกำหนดได้ว่าสิ่งนั้นคืออะไรสิ่งนี้ดีกว่าคำตอบอื่น ๆ และในกรณีส่วนใหญ่คุณควรมองหาสิ่งที่เฉพาะเจาะจงที่คุณสามารถกำหนดได้
abarnert

8

ในการรับประเภทให้ใช้typeฟังก์ชันbuiltin ด้วยinโอเปอเรเตอร์คุณสามารถทดสอบว่าประเภทเป็นประเภทตัวเลขหรือไม่โดยตรวจสอบว่ามีสตริง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

การใช้โมดูลเป็นทางออกที่ดีกว่า
Roland Smith

สามารถใช้ Regex ได้
omkaartg

@ Omkaar.K Regex ใช้ทำอะไรได้บ้าง? หากต้องการทำการตรวจสอบแบบเดียวกันด้วยวิธีที่ซับซ้อนกว่าเล็กน้อย?
ยกเลิก

@abamert "ทำได้" คือสิ่งที่ฉันพูดเช่นกัน regex อาจดูซับซ้อนสำหรับงานง่ายๆเช่นนี้ แต่มีประโยชน์อย่างมากสำหรับงานประมวลผลสตริงขนาดใหญ่ดังนั้นจึงไม่ใช่ความคิดที่ดีที่จะเรียนรู้ ฉันเดาว่าคุณคงรู้แล้วว่าตั้งแต่พอร์ตโฟลิโอของคุณแสดงว่าคุณเป็นโปรแกรมเมอร์อาวุโส
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- 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

สนุกกับบูลีน:

>>> 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!
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.