我对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.)
有什么建议吗?
答案 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. ]])