【问题标题】:initialize numpy array with named tuples用命名元组初始化 numpy 数组
【发布时间】:2014-08-28 15:11:59
【问题描述】:

我正在尝试初始化一个包含命名元组的 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 构造函数的任何提示?

【问题讨论】:

    标签: python arrays numpy initialization namedtuple


    【解决方案1】:

    这很糟糕,但是:

    从复制并粘贴到 ipython 中的示例开始,尝试

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

    它似乎可以解决问题。

    【讨论】:

    • 也就是说,我认为使用empty 的选项也将数据作为迭代器读取。所以可能也好不了多少。主要的问题是,如果一个人也做不到,为什么会想要这样做。
    • 基本点是dtype这样的数组元素是tuplesa[1] 返回 tuple。所以要设置整个数组,你必须使用一个元组列表。 a[:]=[(x,) for x in data] 也可以。
    • 是的,这是 OP 的第一个选项。并且它被声明为工作 - 即使数据数组可能作为迭代器读入(不是 100% 肯定)。所以在这种情况下,甚至不需要转换为元组。问题是关于如何使用 numpy 数组构造函数来处理同样的事情
    【解决方案2】:

    构造一个不同的数组很有指导意义:

    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 列表操作。)

    对于 3 个字段:

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

    奇怪的是,显式转换为 list first 甚至更快(几乎是 zip(data) calc 的 2 倍)

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

    【讨论】:

    • 在这种情况下,以recarray 的身份完成整个事情可能会很有趣
    • zip(data) 使表达式更加简洁。
    猜你喜欢
    • 2020-12-28
    • 2018-12-04
    • 2011-05-30
    • 1970-01-01
    • 2014-06-28
    • 2015-08-05
    • 1970-01-01
    • 1970-01-01
    • 2015-12-25
    相关资源
    最近更新 更多