使用 numpy 堆叠具有一个不同维度的数组
Posted
技术标签:
【中文标题】使用 numpy 堆叠具有一个不同维度的数组【英文标题】:Stacking arrays with one different dimension using numpy 【发布时间】:2021-12-29 15:49:34 【问题描述】:假设我有 2 个数组:
a = np.array([[[1],[1]],[[2],[2]],[[3],[3]],[[4],[4]]])
b = np.array(["a", "b", "c", "d"]).reshape(4,1,1)
然后是a.shape = (4,2,1)
和b.shape=(4,1,1)
。我想要的输出应该是这样的
c = np.array([
[
np.array([[1],[1]]), "a"
],
[
np.array([[2],[2]]), "b"
],
[
np.array([[3],[3]]), "c"
],
[
np.array([[4],[4]]), "d"
],
])
我尝试了np.hstack
和np.concatenate
,但这并不完全符合我的要求。我意识到我可以简单地循环遍历 a
和 b
并创建数组,我只是想知道是否有一个特定的函数会返回数组 c
或者循环是我最好的选择。
【问题讨论】:
我看到的最接近的结果是在轴 1 上使用连接,但这不完全是您的预期结果...请问您为什么需要这个?也许还有其他格式可以满足您的要求.. 为什么要在(object dtype)数组中混合数组和字符串?你认为你会从使用数组中获得一些神奇的速度优势吗?还是这样的数组在计算上比列表更好? 【参考方案1】:您可以结合使用 zip 和 one-liner 进行迭代
a = np.array([[[1],[1]],[[2],[2]],[[3],[3]],[[4],[4]]])
b = np.array(["a", "b", "c", "d"])
c = np.array([[aa,bb] for aa,bb in zip(a,b)])
【讨论】:
这与 OP 使用 for 循环遍历其数组有何不同?我认为他们正在寻找一个特定的 numpy 函数来进行迭代,因为它将被矢量化或至少用 C 编写。 @LiquidSnake,OP 可能不明白他想要什么。c
是一个对象 dtype 数组,因此“矢量化”魔法不适用。【参考方案2】:
我能得到的最接近的是使用np.column_stack([a, b])
。但是,这将包含 numpy 数组中的字符串字符,而不是像您所拥有的那样。
>>> np.column_stack([a,b])
array([[['1'],
['1'],
['a']],
[['2'],
['2'],
['b']],
[['3'],
['3'],
['c']],
[['4'],
['4'],
['d']]], dtype='<U11')
【讨论】:
【参考方案3】:首先删除b
中不必要的维度:
In [203]: b1 = b.ravel()
第二次从a
创建一个4元素对象dtype数组:
In [204]: a1 = np.empty(4, object)
In [205]: a1[:] = list(a)
In [206]: a1
Out[206]:
array([array([[1],
[1]]), array([[2],
[2]]), array([[3],
[3]]), array([[4],
[4]])],
dtype=object)
现在我们可以stack
他们在新的第二个轴上创建一个 (4,2) 数组:
In [207]: np.stack((a1,b1), axis=1)
Out[207]:
array([[array([[1],
[1]]), 'a'],
[array([[2],
[2]]), 'b'],
[array([[3],
[3]]), 'c'],
[array([[4],
[4]]), 'd']], dtype=object)
列表推导更简单,而且可能更快:
In [209]: [[i,j.item()] for i,j in zip(a,b)]
Out[209]:
[[array([[1],
[1]]),
'a'],
[array([[2],
[2]]),
'b'],
[array([[3],
[3]]),
'c'],
[array([[4],
[4]]),
'd']]
或者制作一个包含 2 个字段的结构化数组:
In [215]: c = np.zeros(4, dtype='O,U1')
In [216]: c
Out[216]:
array([(0, ''), (0, ''), (0, ''), (0, '')],
dtype=[('f0', 'O'), ('f1', '<U1')])
In [218]: c['f0'] = list(a)
In [219]: c['f1'] = b.ravel()
In [220]: c
Out[220]:
array([(array([[1],
[1]]), 'a'), (array([[2],
[2]]), 'b'), (array([[3],
[3]]), 'c'),
(array([[4],
[4]]), 'd')], dtype=[('f0', 'O'), ('f1', '<U1')])
或
In [221]: c = np.zeros(4, dtype=[('a',int,(2,1)),('b','U1')])
In [222]: c['a']=a
In [224]: c['b']=b.ravel()
In [225]: c
Out[225]:
array([([[1], [1]], 'a'), ([[2], [2]], 'b'), ([[3], [3]], 'c'),
([[4], [4]], 'd')], dtype=[('a', '<i8', (2, 1)), ('b', '<U1')])
所有这些方法的关键是了解您要创建的内容。您不是在制作“普通”多维数组。您正在尝试混合使用数组和字符串。
您可以concatenate
制作 (4,3,1) - 并通过指定 dtype 来保留整数。这将 (4,2,1) 与中间维度上的 (4,1,1) 连接起来。这就是连接(以及stack
派生类)最擅长的。
In [263]: np.concatenate((a,b),axis=1, dtype=object)
Out[263]:
array([[[1],
[1],
['a']],
[[2],
[2],
['b']],
[[3],
[3],
['c']],
[[4],
[4],
['d']]], dtype=object)
【讨论】:
以上是关于使用 numpy 堆叠具有一个不同维度的数组的主要内容,如果未能解决你的问题,请参考以下文章