关于python:混合类型的NumPy数组/矩阵

NumPy array/matrix of mixed types

我试图创建一个混合数据类型(字符串、整数、整数)的numpy数组/矩阵(nx3)。但是当我通过添加一些数据来附加这个矩阵时,会得到一个错误:类型错误:类型提升无效。拜托,有人能帮我解决这个问题吗?

当我用示例数据创建一个数组时,numpy将矩阵中的所有列强制转换为一个的数据类型。我不能为数组指定数据类型,因为当我这样做时,res=np.array(["text",1,1],dtype='s,i4,i4')-我得到一个错误:type error:需要一个可读的缓冲区对象

模板.py

1
2
3
4
5
6
7
8
9
10
11
12
import numpy as np
from pprint import pprint

test_array = np.zeros((0, 3), dtype='S, i4, i4')
pprint(test_array)

test_array = np.append(test_array, [["TEXT", 1, 1]], axis=0)
pprint(test_array)

print("Array example:")
res = np.array(["TEXT", 1, 1])
pprint(res)

输出:

1
2
3
4
5
array([], shape=(0L, 3L),
  dtype=[('f0', 'S'), ('f1', '<i4'), ('f2', '<i4')])

 Array example:
 array(['TEXT', '1', '1'], dtype='|S4')

错误:

1
2
3
4
5
6
7
8
9
10
Traceback (most recent call last):

File"templates.py", line 5, in <module>
test_array = np.append(test_array, [["TEXT", 1, 1]], axis=0)

File"lib\site-packages
umpy\lib\function_base.py"
, line 3543, in append
return concatenate((arr, values), axis=axis)

TypeError: invalid type promotion


你的问题出在数据上。试试这个:

1
res = np.array(("TEXT", 1, 1), dtype='|S4, i4, i4')

1
res = np.array([("TEXT", 1, 1), ("XXX", 2, 2)], dtype='|S4, i4, i4')

数据必须是元组或元组列表。从错误信息中看不太明显,是吗?

另外,请注意,必须为要真正保存的文本数据指定文本字段的长度。如果要将文本另存为对象(仅引用数组中的对象),则:

1
res = np.array([("TEXT", 1, 1), ("XXX", 2, 2)], dtype='object, i4, i4')

这通常也很有用。


如果你没有嫁给Numpy,熊猫数据框架就是完美的选择。或者,可以将数组中的字符串字段指定为python对象(以dtype='o,i4,i4'为例)。另外,append看起来像元组列表,而不是列表列表。我认为这与列表的可变性有关,不确定。


首先,numpy使用固定的物理记录大小存储数组元素。所以,记录对象都需要具有相同的物理大小。因此,您需要告诉numpy字符串的大小,或者保存一个指向存储在其他地方的字符串的指针。在记录数组中,"s"转换为零长度字符串,这可能不是您想要的。

append方法实际上将整个数组复制到一个更大的物理空间中,以容纳新的元素。尝试,例如:

1
2
3
4
5
6
7
8
import numpy as np
mtype = 'S10, i4, i4'
ta = np.zeros((0), dtype=mtype)
print id(ta)
ta = np.append(ta, np.array([('first', 10, 11)], dtype=mtype))
print id(ta)
ta = np.append(ta, np.array([('second', 20, 21)], dtype=mtype))
print id(ta)

每次以这种方式追加时,复制都会变慢,因为每次增加时需要分配和复制更多的内存。这就是为什么每次追加时ID都返回不同的值。如果您希望数组中有大量的记录,那么最好从一开始就分配足够的空间,或者将数据累积到列表中,然后在完成后将列表收集到一个麻木的结构化数组中。这也使您有机会使mtype中的字符串长度尽可能短,同时仍然足够长以容纳最长的字符串。


我认为这正是您试图实现的目标——创建一个所需dtype的空数组,然后向其添加一个或多个数据集。结果将具有形状(n,n),而不是(n,3)。

正如我在评论中提到的,np.append使用np.concatenate,所以我也在使用它。此外,我还必须分别制作test_arrayx1d阵列(形状(0,)和(1,)。dtype字段是S10,足够大以包含"文本"。

1
2
3
4
5
6
7
8
9
10
11
12
In [56]: test_array = np.zeros((0,), dtype='S10, i4, i4')

In [57]: x = np.array([("TEST",1,1)], dtype='S10, i4, i4')

In [58]: test_array = np.concatenate((test_array, x))

In [59]: test_array = np.concatenate((test_array, x))

In [60]: test_array
Out[60]:
array([('TEST', 1, 1), ('TEST', 1, 1)],
      dtype=[('f0', 'S'), ('f1', '<i4'), ('f2', '<i4')])

下面是从元组列表构建数组的示例:

1
2
3
4
5
6
In [75]: xl=('test',1,1)

In [76]: np.array([xl]*3,dtype='S10,i4,i4')
Out[76]:
array([('test', 1, 1), ('test', 1, 1), ('test', 1, 1)],
      dtype=[('f0', 'S10'), ('f1', '<i4'), ('f2', '<i4')])

我不相信您可以用多个数据类型创建数组。但是,您可以使用多个数据类型创建一个列表。

1
2
list = ["TEXT", 1, 1]
print(list)

给予

1
['TEXT', 1, 1]