首页 > 解决方案 > Numpy,如何将列名添加到 Numpy 数组

问题描述

这可能有一些重复的线程,但老实说我找不到合适的解决方案。Pandas 将是一个简单的解决方案,但在我正在从事的项目中,不会将 pandas 作为依赖项包括在内。

我正在尝试将列名添加到 Numpy 数组中,基本上将其转换为结构化数组,即使数据类型都相同。

我试过了:

signal = np.array([[1,2,3],[1,2,3],[1,2,3]])
col_names = ('left','right','center')
signal = np.array(signal, dtype = [(n, 'int16') for n in col_names])

但这会返回:

array([[(1, 1, 1), (2, 2, 2), (3, 3, 3)],
       [(1, 1, 1), (2, 2, 2), (3, 3, 3)],
       [(1, 1, 1), (2, 2, 2), (3, 3, 3)]],
      dtype=[('left', '<i2'), ('right', '<i2'), ('center', '<i2')])

基本上,我有一个代表多通道信号的 Numpy 数组。我希望能够使用列名对通道进行子集化:

signal['left'] == signal[:,0] # True
signal[['left','center']] == signal[:,[0,2]] # True

我还看到有人建议不要使用结构化数组的帖子。它有潜在的缺点吗?说它使数组访问速度变慢?

标签: pythonarraysnumpy

解决方案


结构化数组的正确数据输入形式是元组列表:

In [71]: signal = [(1,2,3),(2,3,1),(3,2,1)] 
    ...: col_names = ('left','right','center') 
    ...: signal = np.array(signal, dtype = [(n, 'int16') for n in col_names])   
In [72]:                                                                        
In [72]: signal                                                                 
Out[72]: 
array([(1, 2, 3), (2, 3, 1), (3, 2, 1)],
      dtype=[('left', '<i2'), ('right', '<i2'), ('center', '<i2')])

1.16添加了几个函数,可以更轻松地与结构化数组进行转换:

In [73]: import numpy.lib.recfunctions as rfn                                   
In [74]: signal = np.array([[1,2,3],[1,2,3],[1,2,3]])                           
In [75]: dt = np.dtype([(n, 'int16') for n in col_names])                       
In [76]: dt                                                                     
Out[76]: dtype([('left', '<i2'), ('right', '<i2'), ('center', '<i2')])
In [77]: rfn.unstructured_to_structured(signal, dt)                             
Out[77]: 
array([(1, 2, 3), (1, 2, 3), (1, 2, 3)],
      dtype=[('left', '<i2'), ('right', '<i2'), ('center', '<i2')])

应用这个dtsignal问题:

In [82]: signal.view(dt)                                                        
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-82-f0fa01ce8128> in <module>
----> 1 signal.view(dt)

ValueError: When changing to a smaller dtype, its size must be a divisor of the size of original dtype

我们可以通过首先转换signal为兼容的 dtype 来解决这个问题:

In [83]: signal.astype('i2').view(dt)                                           
Out[83]: 
array([[(1, 2, 3)],
       [(1, 2, 3)],
       [(1, 2, 3)]],
      dtype=[('left', '<i2'), ('right', '<i2'), ('center', '<i2')])

但请注意,Out[83]形状是 (3,1)。其他阵列是形状 (3,)。view在转换到结构化数组/从结构化数组转换时一直存在这个形状问题。这就是为什么新功能更易于使用的部分原因。


推荐阅读