用命名元组初始化numpy数组

1 投票
2 回答
2096 浏览
提问于 2025-04-18 18:51

我正在尝试初始化一个包含命名元组的NumPy数组。当我用empty方法初始化数组并在之后设置数据时,一切都很顺利;但是当我使用numpy.array构造函数时,NumPy的表现却和我预期的不一样。

以下是我运行的代码:

import numpy

data = numpy.random.rand(10, 3)
print data[0]

# Works
a = numpy.empty(
    len(data),
    dtype=numpy.dtype([('nodes', (float, 3))])
    )
a['nodes'] = data
print
print a[0]['nodes']


# Doesn't work
b = numpy.array(
    data,
    dtype=numpy.dtype([('nodes', (float, 3))])
    )
print
print b[0]['nodes']

输出结果是:

[ 0.28711363  0.89643579  0.82386232]

[ 0.28711363  0.89643579  0.82386232]

[[ 0.28711363  0.28711363  0.28711363]
 [ 0.89643579  0.89643579  0.89643579]
 [ 0.82386232  0.82386232  0.82386232]]

这是在使用NumPy 1.8.1版本时的情况。

有没有什么建议可以帮助我更好地使用array构造函数呢?

2 个回答

-1

构造一个不同的数组是很有启发性的:

dt3=np.dtype([('x','<f8'),('y','<f8'),('z','<f8')])
b=np.zeros((10,),dtype=dt3)
b[:]=[tuple(x) for x in data]
b['x'] = data[:,0]  # alt
np.array([tuple(x) for x in data],dtype=dt3) # or in one statement

a[:1] 
# array([([0.32726803375966484, 0.5845638956708634, 0.894278688117277],)], dtype=[('nodes', '<f8', (3,))])
b[:1]
# array([(0.32726803375966484, 0.5845638956708634, 0.894278688117277)], dtype=[('x', '<f8'), ('y', '<f8'), ('z', '<f8')])

我觉得要把 data 赋值给 b 的所有字段,肯定得用某种循环。


genfromtxt 是生成这种记录数组的常用方法。看它的代码,我发现了一个模式:

data = list(zip(*[...]))
output = np.array(data, dtype)

这让我想尝试一下:

dtype=numpy.dtype([('nodes', (float, 3))])
a = np.array(zip(data), dtype=dtype)

(速度基本和 eickenberg 的理解差不多;所以它在做的也是一样的纯 Python 列表操作。)

对于这三个字段:

np.array(zip(*data.T), dtype=dt3)

有趣的是,先显式转换为列表的速度甚至更快(几乎是 zip(data) 计算的两倍)

np.array(zip(*data.T.tolist()), dtype=dt3)
0

这真让人头疼,不过:

从你复制粘贴的例子开始,放到ipython里试试

dtype=numpy.dtype([('nodes', (float, 3))])
c = numpy.array([(aa,) for aa in data], dtype=dtype)

这样似乎就能解决问题了。

撰写回答