在numpy数组中定义列 - TypeError:无效的类型提升

时间:2016-10-02 08:45:31

标签: python numpy

我正在定义一个看起来像这样的数组

['word1', 2000, 21]
['word2', 2002, 33]
['word3', 1988, 51]
['word4', 1999, 26]
['word5', 2001, 72]

然而,当我追加一个新条目时,我得到一个TypeError。

import numpy as np

npdtype = [('word', 'S35'), ('year', int), ('wordcount', int)]
np_array = np.empty((0,3), dtype=npdtype)

word = 'word1'
year = '2001'
word_count = '21'

np_array = np.append(np_array, [['word1', int(year), int(word_count)]], axis=0)

追溯

 File "/home/matt/.local/lib/python2.7/site-packages/numpy/lib/function_base.py", line 4586, in append
return concatenate((arr, values), axis=axis)
 TypeError: invalid type promotion

我做错了什么?

由于

2 个答案:

答案 0 :(得分:1)

append是一种调用np.concatenate的方式。看看它的代码。注意,它必须确保第二个参数是一个数组。如果不了解您的特殊dtype,就可以做到这一点。试试吧。它可能会产生一个字符串dtype。然后它尝试连接。所以你需要先用正确的dtype创建一个数组。

我不鼓励使用append;最好直接使用concatenate,以便了解所有细节。

======================

扩大答案:

In [75]: npdtype
Out[75]: [('word', 'S35'), ('year', numpy.int16), ('wordcount', numpy.int16)]
In [76]: column = np.array( [b'word1', np.int16(year), np.int16(word_count)], dtype=npdtype)
In [77]: column
Out[77]: 
array([(b'word1', 0, 0), 
       (b'\xd1\x07', 0, 0), 
       (b'\x15', 0, 0)], 
      dtype=[('word', 'S35'), ('year', '<i2'), ('wordcount', '<i2')])

我认为这不是你想要的。

为结构化数组记录提供数据的正确方法是使用元组或元组列表(注意extra()):

In [78]: column = np.array( [(b'word1', np.int16(year), np.int16(word_count))], dtype=npdtype)
In [79]: column
Out[79]: 
array([(b'word1', 2001, 21)], 
      dtype=[('word', 'S35'), ('year', '<i2'), ('wordcount', '<i2')])
In [80]: column.shape
Out[80]: (1,)

现在我有一个包含3个字段的1d,1个元素数组。

没有[],我得到一个单元素0d数组

In [81]: column0 = np.array( (b'word1', np.int16(year), np.int16(word_count)), dtype=npdtype)
In [82]: column0.shape
Out[82]: ()
In [83]: column0
Out[83]: 
array((b'word1', 2001, 21), 
      dtype=[('word', 'S35'), ('year', '<i2'), ('wordcount', '<i2')])

我可以连接几个1d数组:

In [85]: np.concatenate([column,column,column])
Out[85]: 
array([(b'word1', 2001, 21), 
       (b'word1', 2001, 21), 
       (b'word1', 2001, 21)], 
      dtype=[('word', 'S35'), ('year', '<i2'), ('wordcount', '<i2')])
In [86]: _.shape
Out[86]: (3,)
In [87]: __['year']   # access the 2nd field (not column)
Out[87]: array([2001, 2001, 2001], dtype=int16)

关于b的需要。您正在使用Py3(就像我一样),unicode是默认的字符串类型。因此,如果您在U35中使用了npdtype,则可能会遗漏b(bytestring标志)。

(0,3)形状初始数组可能不是你想要的。 0行,3列,但仍有3个dtype字段。查看(1,3)版本

In [88]: np.empty((1,3),dtype=npdtype)
Out[88]: 
array([[(b'', 0, 0), (b'', 0, 0), (b'', 0, 0)]], 
      dtype=[('word', 'S35'), ('year', '<i2'), ('wordcount', '<i2')])

由于内存中发生了什么,这有空白和0。它们可能是随机字符/数字。

numpy允许您创建具有一个或多个0维的数组,但它们通常没用。关于它们出现的唯一位置是迭代数组定义的起点,例如

 arr = np.empty((0,3))
 for i in range(10):
     arr = np.append(arr, [i,i+1,i+2])

哪个更好写为

 ll = []
 for i in range(10):
     ll.append([i,i+1,i+2])
 arr = np.array(ll)

 arr = np.empty((10,3))
 for i in range(10):
     arr[i,:]=[i,i+1,i+2]

重复数组连接速度较慢。

答案 1 :(得分:0)

按照@ hpaulj的建议,然后收拾整齐。

import numpy as np

npdtype = [('word', 'S35'), ('year', np.int16), ('wordcount', np.int16)]
np_array = np.empty((0,3), dtype=npdtype)

word = 'word1'
year = '2001'
word_count = '21'

column = np.array( [b'word1', np.int16(year), np.int16(word_count)], dtype=npdtype)
print (column.shape)
column.shape=-1,3
print (column.shape)
print (column)
result=np.concatenate((np_array,column),axis=0)
print (result)

#~ np_array = np.append(np_array, [['word1', int(year), int(word_count)]], axis=0)

我发现的两件事:

  • 需要对记录项类型进行细致的匹配,因此在npdtype的定义和字符串的转换中使用numpy类型;并且还将 b 前缀用于记录的第一个元素。
  • 创建的列具有奇特的形状,因此需要重新整形。

这是输出。

>pythonw -u "temp.py"
(3,)
(1, 3)
[[(b'word1', 0, 0) (b'\xd1\x07', 0, 0) (b'\x15', 0, 0)]]
[[(b'word1', 0, 0) (b'\xd1\x07', 0, 0) (b'\x15', 0, 0)]]
>Exit code: 0