Arrays Python:附加到numpy数组
在某些情况下,希望连接的numpy数组覆盖原始numpy数组。 我想讨论一个复杂结构数组中的numpy数组示例。 这个问题是通过回答一个关于结构化数组的问题而产生的 类似问题 有几种方法,如Arrays Python:附加到numpy数组,arrays,python-2.7,numpy,Arrays,Python 2.7,Numpy,在某些情况下,希望连接的numpy数组覆盖原始numpy数组。 我想讨论一个复杂结构数组中的numpy数组示例。 这个问题是通过回答一个关于结构化数组的问题而产生的 类似问题 有几种方法,如numpy.append,numpy.concatenate,numpy.vstack或numpy.hstack 它们中的每一个都会创建一个新数组,不能通过返回如下错误消息将该数组分配回旧变量: ValueError: could not broadcast input array from sha
numpy.append
,numpy.concatenate
,numpy.vstack
或numpy.hstack
ValueError: could not broadcast input array from shape (1,2,3) into shape (1,2,2)
可能的方法
作为一个简单但耗时的解决方案,我可以定义一个新的空numpy数组,用旧数据和应该追加的数据填充该数组
还感谢您提供其他解决方案。A
numpy
数组将其数据保存在固定大小的缓冲区中。诸如shape
、strips
和dtype
等属性用于解释该数据。这些属性可以更改,数据缓冲区中的值也可以更改。但是任何改变缓冲区大小的操作都需要一个副本
追加
,连接
等都会创建一个新数组,并用原始数组中的数据填充它
您的append
操作将创建一个新的(1,2,3)
数组。它不能替换x
缓冲区中的(1,2,2)
字节字符串
如果将('Table',float64,(2,2))
替换为('Table',object)
,则可以更改x['Table']
。这是因为x
现在包含一个指向单独数组的指针。赋值将一个指针替换为另一个指针,而不更改x
缓冲区的大小。这就像更改字典的值,或者替换列表中的嵌套列表
为什么要尝试使用结构化数组而不是传统的Python结构,如list
、dict
或自定义类对象
下面是一个有效的序列:
In [116]: x = np.zeros(1, dtype = [('Table', 'O'),
('Number', np.float),
('String', '|S10')])
In [117]: x['Table'][0] = np.zeros((2,2),dtype=np.float64)
In [118]: x['Table'][0] = np.append(x['Table'][0], np.array([[[1], [2]]]))
In [119]: x
Out[119]:
array([([0.0, 0.0, 0.0, 0.0, 1.0, 2.0], 0.0, '')],
dtype=[('Table', 'O'), ('Number', '<f8'), ('String', 'S10')])
x['Table']
是另一个结构化数组
回顾原始的x
定义,让我们给它3行(元素):
但无论如何,我都无法扩展它,除非创建一个新的x
数组
另一种类似于构造的结构是字典:
In [156]: x={'Table': np.zeros((1,2,2),dtype=np.float64),
'Number':np.zeros((1,)),
'String':['']}
In [157]: x
Out[157]:
{'Number': array([ 0.]),
'String': [''],
'Table': array([[[ 0., 0.],
[ 0., 0.]]])}
In [158]: x['Table'] =np.append(x['Table'],[1,2])
In [159]: x
Out[159]:
{'Number': array([ 0.]),
'String': [''],
'Table': array([ 0., 0., 0., 0., 1., 2.])}
从CSV文件读取时,这样复杂的数据结构最有意义。比如说
In [161]: dt = np.dtype([('Table', np.float64, (2, 2)),
('Number', np.float),
('String', '|S10')])
In [162]: txt="""0 0 0 0 0 astring
.....: 1 2 3 4 0 another
.....: 1 1 1 1 10 end
.....: """
In [163]: A=np.genfromtxt(txt.splitlines(),dtype=dt)
In [164]: A
Out[164]:
array([([[0.0, 0.0], [0.0, 0.0]], 0.0, 'astring'),
([[1.0, 2.0], [3.0, 4.0]], 0.0, 'another'),
([[1.0, 1.0], [1.0, 1.0]], 10.0, 'end')],
dtype=[('Table', '<f8', (2, 2)), ('Number', '<f8'), ('String', 'S10')])
[161]中的:dt=np.dtype([('Table',np.float64,(2,2)),
(“数字”,名词性浮点数),
('String','S10'))
在[162]:txt=“”0 0 0 0 0 0 0 0
…1 2 3 4 0另一个
..:110结束
.....: """
在[163]中:A=np.genfromtxt(txt.splitlines(),dtype=dt)
在[164]中:A
出[164]:
数组([([[0.0,0.0],[0.0,0.0]],0.0,'astring'),
([1.0,2.0],[3.0,4.0],[0.0,'另一个'),
([1.0,1.0],[1.0,1.0],[10.0,'end'),
dtype=[('Table',如果我对numpy的理解正确,它会将其数据放入连续内存块中。因此我不确定numpy是否适合您的任务。您可能需要查看pytables(),它是为处理分层数据而设计的。@Dietrich:我不太清楚numpy
,尽管它没有直接回答这个问题,但请您再详细一点好吗?请记住:我不想将这个数组写入文件(如h5或txt)。它只是用于内部操作。如果您的内部数据结构类似于链表(我不确定,但我认为python的列表是以这种方式实现的),则追加是有效的。如果您放大一个numpy数组,它将不得不将您的数据复制到一个新的内存位置,因为它无法在当前块后面找到可用内存。因此,我认为没有比您建议的更有效的方法了-除非您使用不同的数据结构:根据数据大小,python列表或dict可能就足够了用于大型阵列(RAM的重要部分),我建议使用pytables或数据库。@Dietrich:如果我理解正确,在扩展列表时使用列表更有效。您也建议使用pytables或数据库,但前提是它可能超过我的RAM?我不想在这里讨论这种情况。确切地说,我连续构建阵列的标准策略是使用在我的经验中,预分配足够大的数据块和移动原始数据(请参见numpy.getbuffer()
)在大多数情况下可以忽略不计。
In [132]: x = np.zeros(3, dtype = [('Table', np.float64, (2, 2)),
('Number', np.float),
('String', '|S10')])
In [133]: x
Out[133]:
array([([[0.0, 0.0], [0.0, 0.0]], 0.0, ''),
([[0.0, 0.0], [0.0, 0.0]], 0.0, ''),
([[0.0, 0.0], [0.0, 0.0]], 0.0, '')],
dtype=[('Table', '<f8', (2, 2)), ('Number', '<f8'), ('String', 'S10')])
In [134]: x['Table'].shape
Out[134]: (3, 2, 2)
In [137]: x['Table'][0,0,:]=[1,1]
In [156]: x={'Table': np.zeros((1,2,2),dtype=np.float64),
'Number':np.zeros((1,)),
'String':['']}
In [157]: x
Out[157]:
{'Number': array([ 0.]),
'String': [''],
'Table': array([[[ 0., 0.],
[ 0., 0.]]])}
In [158]: x['Table'] =np.append(x['Table'],[1,2])
In [159]: x
Out[159]:
{'Number': array([ 0.]),
'String': [''],
'Table': array([ 0., 0., 0., 0., 1., 2.])}
In [161]: dt = np.dtype([('Table', np.float64, (2, 2)),
('Number', np.float),
('String', '|S10')])
In [162]: txt="""0 0 0 0 0 astring
.....: 1 2 3 4 0 another
.....: 1 1 1 1 10 end
.....: """
In [163]: A=np.genfromtxt(txt.splitlines(),dtype=dt)
In [164]: A
Out[164]:
array([([[0.0, 0.0], [0.0, 0.0]], 0.0, 'astring'),
([[1.0, 2.0], [3.0, 4.0]], 0.0, 'another'),
([[1.0, 1.0], [1.0, 1.0]], 10.0, 'end')],
dtype=[('Table', '<f8', (2, 2)), ('Number', '<f8'), ('String', 'S10')])