在NumPy数组中检查类型

32

我拥有不同类型的数据,其中大部分是int类型,有时候也会有float类型。这些int类型的数据大小不同,它们的大小可能是8/16/32个比特位。
针对这种情况,我正在创建一个数值类型转换器。因此我使用isinstance()检查变量的类型。我读到isinstance()type()要好一些。

问题在于,我得到了许多numpy数组数据。我使用Spyder作为IDE,并通过变量来查看它们的类型。但是当我输入isinstance(var,'我所读到的类型')时,返回值却是False

我进行了一些检查:

a = 2.17 
b = 3 
c = np.array(np.random.rand(2, 8))
d = np.array([1])

对于isinstance(var, type),我得到:

isinstance(a, float)
True
isinstance(b, int)
True
isinstance(c, float)  # or isinstance(c, np.float64)
False
isinstance(d, int)  # or isinstance(c, np.int32)
False

cd在我询问时为真。

isinstance(c, np.ndarray)
True
isinstance(d, np.ndarray)
True
我可以通过在ndarray中执行步骤来进行检查
isinstance(c[i][j], np.float64)
True
isinstance(d[i], np.int32)
True

但这意味着对于每个维度,我都必须添加一个新索引,否则它又变成了False。 可以使用dtype检查它们的类型,例如c.dtype == 'float64'...

那么根据我所发现和尝试的内容... 我的问题基本上是:

  • var.dtype 方法与 isinstance()type()(更差/更好等)相比如何?
  • 如果 var.dtypeisinstance() 更糟糕,那么是否有一种方法可以在 isinstance() 中自动进行索引(自动索引等)?

你有不同整数大小的数据在哪里?是作为Python对象、numpy数组还是文件?你可能需要提供更多上下文来使用数值类型转换器。 - hpaulj
大多数是多声道音频文件。 - Jan-Bert
你打算如何转换数据类型? - hpaulj
从 int 类型 / numpy.intXX 类型更改为 (numpy.)float(64),并按整数大小缩小比例。因此,所有内容都是 -1 最小值到 +1 最大值。 - Jan-Bert
我在我的回答中添加了关于np.can_cast.astype的注释。 - hpaulj
5个回答

41
一个数组是np.ndarray类型的对象。 它的值或元素存储在数据缓冲区中,可以将其视为连续的内存字节块。 数据缓冲区中的字节没有类型,因为它们不是Python对象。
数组具有dtype参数,用于解释这些字节。 如果dtypeint32(有各种同义词),则4个字节将被解释为整数。 访问一个元素,例如c [0],会给出一个取决于dtype的新对象,例如np.int32类型的对象。 c [0] .item将返回相应类型的Python对象:
In [2102]: c=np.array([1])
In [2103]: c.dtype
Out[2103]: dtype('int32')
In [2104]: type(c)
Out[2104]: numpy.ndarray
In [2105]: type(c[0])
Out[2105]: numpy.int32
In [2107]: c[0].item()
Out[2107]: 1
In [2108]: type(c[0].item())
Out[2108]: int

(而且 c[0].dtypec.dtype 的类型是相同的;检查数组元素的类型时不需要对单个元素进行索引)。

这个数组的相同4个字节可以被看作是int8类型——一个单字节整数。

In [2112]: c.view('b')
Out[2112]: array([1, 0, 0, 0], dtype=int8)

这种备选视图中的单个元素是np.int8,但是当我使用item()时,会得到一个Python整数。Python没有int8数字类型。

In [2113]: type(c.view('b')[0])
Out[2113]: numpy.int8
In [2115]: type(c.view('b')[0].item())
Out[2115]: int
一个列表包含指向Python对象的指针,每个对象都有一个类型。数组dtype=object也是如此。但是常见的数值数组并不包含Python整数或浮点数。它具有数据缓冲区,可以根据dtype以各种方式进行解释。Python整数并没有不同的大小,至少与numpy dtypes不同。
因此,isinstancetype()等内容不适用于ndarray的内容。
====================
从评论中我了解到您正在尝试将整数数组转换为浮点数。您没有转换标量。如果是这样,那么dtype就是唯一重要的;数组总是有一个dtype。不清楚您是否接受将np.float32转换为np.float64
我建议学习和尝试使用np.can_cast函数和x.astype方法。
x.astype(np.float64, copy=False)
例如,将所有整数数据类型转换为浮点数,而不复制已经是float64的部分。它可能会复制并转换np.float32的部分。
还要注意这些函数的casting参数。
===========================
我在scipy.optimize.minimize中找到了另一个测试工具。
In [156]: np.typecodes
Out[156]: 
{'All': '?bhilqpBHILQPefdgFDGSUVOMm',
 'AllFloat': 'efdgFDG',
 'AllInteger': 'bBhHiIlLqQpP',
 'Character': 'c',
 'Complex': 'FDG',
 'Datetime': 'Mm',
 'Float': 'efdg',
 'Integer': 'bhilqp',
 'UnsignedInteger': 'BHILQP'}

它可以用来检查整数:

if x0.dtype.kind in np.typecodes["AllInteger"]:
    x0 = np.asarray(x0, dtype=float)

8
直接回答这个问题,你可以这样做:
isinstance(arr.flat[0], np.floating)
.flat会将任意数量的维度降低,因此您可以轻松访问第0个元素。
np.floating将匹配任何numpy浮点类型。

2
这假设数组第一个元素。它可能没有 - 数组可以有0个元素。这严格劣于dtype检查。 - user2357112

5

和@rasen58和@hpaulj的做法略有不同:

要检查一个np数组是否包含浮点类型的元素,对我来说c.dtype == np.floating很有效。


2
就我个人而言,当我尝试这个时,我得到了/usr/local/lib/python3.7/dist-packages/ipykernel_launcher.py:79: DeprecationWarning: Converting 'np.inexact' or 'np.floating' to a dtype is deprecated. The current result is 'float64' which is not strictly correct.的警告信息。 - Craig Reynolds
1
然而,对我来说使用 c.dtype == np.double 是有效的。有关numpy类型名称的更多信息,请参见此处:https://numpy.org/doc/stable/user/basics.types.html - Craig Reynolds
1
当我测试 c.dtype == float 而不是 c.dtype == np.floating 时,@CraigReynolds 描述的警告消失了。我不太确定这些测试是否等效,但在我的情况下,我得到了预期的结果。 - Malo Pocheau
感谢@Malo Pocheau。那时候我还很年轻,很天真,大约4个月前才接触Python、numpy和深度学习…… - Craig Reynolds

1
所有numpy数组中的元素都是相同类型的。Numpy类型和Python类型不是同一回事。这可能有点令人困惑,但numpy所指的类型更像C语言等语言使用的类型 - 你可以说更接近机器级别。
你不能说哪种类型更好,因为这就像比较苹果和橙子。

你应该说“所有条目...都是相同的dtype”,以及“numpy dtype”。数组的类型是“ndarray”,无论其“dtype”如何。 - hpaulj

-1
我编写了一个小的包装器,基本上像isinstance一样工作,并接受一个对象o和一个类(或类组成的元组)c。唯一的区别是如果isinstance(o,np.ndarray)为True,则检查o.flat [0]是否与映射的numpy数据类型匹配(请参见dict c2np)。我主要使用bool、int、float、str,但这个列表可以改变/扩展。请注意,np.integer和np.floating是大多数/所有可用的numpy子类型的集合,如np.int8、np.unit16等。
def np_isinstance(o, c):
    c2np = {bool: np.bool, int: np.integer, float: np.floating, str: np.str}

    if isinstance(o, np.ndarray):
        c = (c2np[cc] for cc in c) if isinstance(c, tuple) else c2np[c]
        return isinstance(o.flat[0], c)

    else:
        return isinstance(o, c)

一些例子:

# Like isinstance if o is not np.ndarray
np_isinstance(('this', 'that'), tuple)  # True
np_isinstance(4.4, int)                 # False
np_isinstance(4.4, float)               # True

#
np_isinstance(np.ones(4, dtype=int), int)    # True
np_isinstance(np.ones(4, dtype=int), float)  # False
np_isinstance(np.full((4, 4), 'bert'), str)  # True

这对于布尔值失败,并且严格劣于dtype检查。 - user2357112

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接