展平数组的元组数组

时间:2018-04-03 17:01:19

标签: python arrays numpy

我对numpy和数组的处理都很陌生,我遇到了以下问题。我有一个看起来像这样的数组:

[ (float, array([ float]), array([ float, float]), int, int, float)
  ... ]

即。在我看来,数组的每个元素都是一个元组,包含float,int和float数组的混合。我想知道1)如何摆脱 in 里面的元组结构只保留第一个索引,以及2)最有效的方法是什么。

例如,如果第一个元组是:

(1.2, array([ 0.03]), array([ 1.8, 2.1]), 2, 4, 2.)

我想得到:

(1.2, 0.03, 1.8, 2, 4, 2.)

有什么建议吗?

2 个答案:

答案 0 :(得分:1)

这是使用itertools.chain的一种方式。假设项目是标量或numpy数组。

import numpy as np
from itertools import chain

tup = [(1.2, np.array([ 0.03]), np.array([ 1.8, 2.1]), 2, 4, 2.),
       (5.2, np.array([ 0.345]), np.array([ 11.8, 25.1]), 7, 1, 12.)]

res = list(chain.from_iterable(chain.from_iterable(i.tolist() \
           if isinstance(i, np.ndarray) else [i] for i in j) for j in tup))

# [1.2, 0.03, 1.8, 2.1, 2, 4, 2.0, 5.2, 0.345, 11.8, 25.1, 7, 1, 12.0]

答案 1 :(得分:1)

构建类似的结构化数组:

In [333]: dt=[('var1', '<f4'), ('var2', 'O'), ('var3', 'O'), ('var4', '<i4')]
In [334]: arr = np.zeros(3, dt)
In [335]: arr
Out[335]: 
array([(0., 0, 0, 0), (0., 0, 0, 0), (0., 0, 0, 0)],
      dtype=[('var1', '<f4'), ('var2', 'O'), ('var3', 'O'), ('var4', '<i4')])

用数据填充(现在是相同的副本):

In [336]: arr[0]=(1.2, np.array([.03]),np.array([1.8,2.1]),2)
In [337]: arr[1]=(1.2, np.array([.03]),np.array([1.8,2.1]),2)
In [338]: arr[2]=(1.2, np.array([.03]),np.array([1.8,2.1]),2)
In [339]: arr
Out[339]: 
array([(1.2, array([0.03]), array([1.8, 2.1]), 2),
       (1.2, array([0.03]), array([1.8, 2.1]), 2),
       (1.2, array([0.03]), array([1.8, 2.1]), 2)],
      dtype=[('var1', '<f4'), ('var2', 'O'), ('var3', 'O'), ('var4', '<i4')])

tolist不会移除或压平内部数组:

In [340]: arr.tolist()
Out[340]: 
[(1.2000000476837158, array([0.03]), array([1.8, 2.1]), 2),
 (1.2000000476837158, array([0.03]), array([1.8, 2.1]), 2),
 (1.2000000476837158, array([0.03]), array([1.8, 2.1]), 2)]

使用更简单的结构化dtypes,np.array(arr.tolist())经常有效,因为np.array会尝试创建多维数组。但这里的第一个元素是float,但第二个元素是一个数组:

In [341]: np.array(_)
ValueError: setting an array element with a sequence.

我们可以从该列表中创建一个对象dtype数组 - 但是仍然没有解压缩内部数组:

In [342]: np.array(arr.tolist(),object)
Out[342]: 
array([[1.2000000476837158, array([0.03]), array([1.8, 2.1]), 2],
       [1.2000000476837158, array([0.03]), array([1.8, 2.1]), 2],
       [1.2000000476837158, array([0.03]), array([1.8, 2.1]), 2]],
      dtype=object)

我可以打开&#39; var2&#39;字段:

In [345]: arr['var2'].astype(float)
Out[345]: array([0.03, 0.03, 0.03])
In [346]: arr['var2'][:] = _
In [347]: arr
Out[347]: 
array([(1.2, 0.03, array([1.8, 2.1]), 2),
       (1.2, 0.03, array([1.8, 2.1]), 2),
       (1.2, 0.03, array([1.8, 2.1]), 2)],
      dtype=[('var1', '<f4'), ('var2', 'O'), ('var3', 'O'), ('var4', '<i4')])

但这并不适用于&#39; var3&#39;领域。但是如果你只是想要每个&#39; var3&#39;的第一个元素。阵列:

In [353]: arr['var3']
Out[353]: 
array([array([1.8, 2.1]), array([1.8, 2.1]), array([1.8, 2.1])],
      dtype=object)

In [355]: np.stack(arr['var3'])  # only works if all have the same length
Out[355]: 
array([[1.8, 2.1],
       [1.8, 2.1],
       [1.8, 2.1]])
In [356]: np.stack(arr['var3'])[:,0]
Out[356]: array([1.8, 1.8, 1.8])
In [357]: arr['var3']=_
In [358]: arr
Out[358]: 
array([(1.2, 0.03, 1.8, 2), (1.2, 0.03, 1.8, 2), (1.2, 0.03, 1.8, 2)],
      dtype=[('var1', '<f4'), ('var2', 'O'), ('var3', 'O'), ('var4', '<i4')])
In [359]: np.array(arr.tolist())
Out[359]: 
array([[1.20000005, 0.03      , 1.8       , 2.        ],
       [1.20000005, 0.03      , 1.8       , 2.        ],
       [1.20000005, 0.03      , 1.8       , 2.        ]])

将这个数组作为一个元组列表处理,并迭代处理它可能会更好。

首先,概括数组的元素:

In [360]: arr[0]=(1.2, np.array([.03]),np.array([1.8,2.1]),2)
In [361]: arr[1]=(1.2, np.array([.03,.4]),np.array([1.8,2.1,.2]),2)
In [362]: arr[2]=(1.2, np.array([.03,.4]),np.array([1.8]),2)
In [363]: arr
Out[363]: 
array([(1.2, array([0.03]), array([1.8, 2.1]), 2),
       (1.2, array([0.03, 0.4 ]), array([1.8, 2.1, 0.2]), 2),
       (1.2, array([0.03, 0.4 ]), array([1.8]), 2)],
      dtype=[('var1', '<f4'), ('var2', 'O'), ('var3', 'O'), ('var4', '<i4')])

定义一个拉取数组第一个元素的辅助函数:

In [364]: def foo(item):
     ...:     try:
     ...:         return item[0]
     ...:     except:
     ...:         return item
     ...:     

现在迭代元组,并在元组内:

In [365]: [[foo(item) for item in a] for a in arr]
Out[365]: [[1.2, 0.03, 1.8, 2], [1.2, 0.03, 1.8, 2], [1.2, 0.03, 1.8, 2]]

如果需要,将其转回数组:

In [366]: np.array(_)
Out[366]: 
array([[1.20000005, 0.03      , 1.8       , 2.        ],
       [1.20000005, 0.03      , 1.8       , 2.        ],
       [1.20000005, 0.03      , 1.8       , 2.        ]])