我有两个矩阵(m1和m2),大小为125,30,360,包含不同长度的数组。我想要做的是按元素连接这些数组。现在,我使用for循环执行此操作:
for i in range(125):
for j in range(30):
for k in range(360):
m1[i, j, k] = np.hstack(m1[i, j, k], m2[i, j, k])
因此,生成的m1
仍然具有与之前相同的大小,但是,每个元素中的数组都已更改长度。上面的例子有效,但需要很长时间(我在代码中多次这样做)。有更快的方法吗?如果有明确说明,则m1
和m2
创建如下:
m1 = np.zeros([125, 30, 360], dtype=np.ndarray)
for i in range(125):
for j in range(30):
for k in range(360):
m1[i,j,k] = np.array([])
编辑:我上面的文字有点不清楚,这导致了一些混乱。因此,我在下面创建了一个我想做的小例子。
步骤1:创建m1和m2。
m1 = np.zeros([2, 2], dtype=np.ndarray)
m2 = np.zeros([2, 2], dtype=np.ndarray)
for i in range(2):
for j in range(2):
m1[i, j] = np.array(range(i+j))
m2[i, j] = np.array(range(i+j+1))
步骤1导致:
m1 = array([[array([], dtype=float64), array([0])],
[array([0]), array([0, 1])]], dtype=object)
m2 = array([[array([0]), array([0, 1])],
[array([0, 1]), array([0, 1, 2])]], dtype=object)
步骤2:连接m1和m2。
for i in range(2):
for j in range(2):
m1[i, j] = np.hstack((m1[i, j], m2[i, j]))
步骤2导致:
m1 = array([[array([ 0.]), array([0, 0, 1])],
[array([0, 0, 1]), array([0, 1, 0, 1, 2])]], dtype=object)
所以,问题是:第2步可以更快完成吗?
答案 0 :(得分:0)
In [164]: m1 = np.zeros([2, 2], dtype=np.ndarray)
...: m2 = np.zeros([2, 2], dtype=np.ndarray)
...: for i in range(2):
...: for j in range(2):
...: m1[i, j] = np.array(range(i+j))
...: m2[i, j] = np.array(range(i+j+1))
...:
结果是dtype对象的2个2d数组。 dtype=np.ndarray
对于object
定义的集合中的任何内容都会变为dtypes
。
In [165]: m1
Out[165]:
array([[array([], dtype=float64), array([0])],
[array([0]), array([0, 1])]], dtype=object)
In [166]: m1.shape
Out[166]: (2, 2)
In [167]: m2.shape
Out[167]: (2, 2)
In [168]: m1[0,0]
Out[168]: array([], dtype=float64)
m1
是一个二维数组,包含指向内存中其他对象的指针。在你的情况下,它们是数组,但它们可以是列表,dicts,None
,字符串或数字甚至函数。
这样的数组可以被描述为一个美化列表,因为它具有形状(2d),可以被重新整形,并且在少数情况下它甚至会将数学运算投射到元素(例如m1*2
)。或者它可能是一个贬值的列表,因为它没有append
等方法。
在大多数情况下,对此类数组的numpy
操作需要Python级迭代。并且具有需要双循环或等效的2d形状。
与任何nd数组一样,你可以绕过扁平化的嵌套循环;例如,列表理解:
In [173]: [np.concatenate((a,b)) for a,b in zip(m1.flat, m2.flat)]
Out[173]: [array([ 0.]), array([0, 0, 1]), array([0, 0, 1]), array([0, 1, 0, 1, 2])]
In [174]: np.array([np.concatenate((a,b)) for a,b in zip(m1.flat, m2.flat)]).reshape(2,2)
Out[174]:
array([[array([ 0.]), array([0, 0, 1])],
[array([0, 0, 1]), array([0, 1, 0, 1, 2])]], dtype=object)
这是frompyfunc
可能有用的情况,为您处理更高维度。我发现它提供了一个适度的(最多2倍)加速更明确的循环:
In [177]: f=np.frompyfunc(lambda a,b: np.concatenate((a,b)),2,1)
In [178]: f(m1,m2)
Out[178]:
array([[array([ 0.]), array([0, 0, 1])],
[array([0, 0, 1]), array([0, 1, 0, 1, 2])]], dtype=object)
总之,与n-d数值数组上的类似操作相比,对象数组上的任何元素操作都会很慢。