在循环中堆叠numpy数组的最快方法是什么?

7
我有一个代码,在一个for循环内生成了两个numpy数组(data_transform)。第一次循环生成一个numpy数组(40,2),第二次循环生成一个numpy数组(175,2)。我想把这两个数组合并成一个,得到一个(215,2)的数组。我尝试使用np.concatenatenp.append,但由于数组大小必须相同,所以它给我返回了一个错误。以下是我编写代码的示例:
result_arr = np.array([])

for label in labels_set:
    data = [index for index, value in enumerate(labels_list) if value == label]
    for i in data:
        sub_corpus.append(corpus[i])
    data_sub_tfidf = vec.fit_transform(sub_corpus) 
    data_transform = pca.fit_transform(data_sub_tfidf) 
    #Append array
    sub_corpus = []

我也使用过 np.row_stack,但没有其他方法给我一个值为(175, 2)的数组,这是我想要连接的第二个数组。


你在开头赋值了 result_arr,为什么?然后在循环中又重新赋值了它-但没有将其作为 row_stack 的参数使用。您是在尝试模仿列表“追加”循环吗? - hpaulj
@hpaulj 我想创建一个空数组并填充它。我只想执行当我向列表添加值时所做的操作。 - Luis Miguel
坚持使用列表附加; 不要试图用数组模仿它。在最后一步中完成数组。 - hpaulj
alist.append(x)alist 上进行原地操作。np.row_stack(data_transform) 返回一个新的数组。它不使用或操作 result_arr,在该表达式中根本没有出现。result_arr=... 步骤只是用新值替换了先前的值。这个语法与列表代码完全不同。 - hpaulj
@hpaulj 我知道,但我想用 numpy 执行 alist.append() 的操作。 - Luis Miguel
列表附加会添加一个指针/引用到自身。对于数组来说,没有类似的操作。要连接两个数组,您必须创建一个新的数组。这比简单的列表附加更昂贵。而且,您必须密切关注各自数组的形状 - concatenate(以及堆栈变体)对此非常挑剔。 - hpaulj
3个回答

13

@hpaulj的意思是在循环时要坚持使用列表附加。

#use a normal list
result_arr = []

for label in labels_set:

    data_transform = pca.fit_transform(data_sub_tfidf) 

    # append the data_transform object to that list
    # Note: this is not np.append(), which is slow here
    result_arr.append(data_transform)

# and stack it after the loop
# This prevents slow memory allocation in the loop. 
# So only one large chunk of memory is allocated since
# the final size of the concatenated array is known.

result_arr = np.concatenate(result_arr)

# or 
result_arr = np.stack(result_arr, axis=0)

# or
result_arr = np.vstack(result_arr)

你的数组并没有真正不同的维度,它们只有一个不同的维度,另一个维度是相同的。在这种情况下,你总是可以沿着“不同”的维度堆叠。


这里np.concatenatenp.stack实际上有区别吗?concatenate似乎是将它们按列连接到矩阵中,而stack似乎是将它们按行堆叠在彼此上方。 - MJimitater
如果您想在for循环中垂直连接多个2D数组,而不使用np.vstack()怎么办? - VMMF
你如何确保它不是np附加? - Ana

1
使用连接函数,初始化"c":
a = np.array([[8,3,1],[2,5,1],[6,5,2]])
b = np.array([[2,5,1],[2,5,2]])
matrix = [a,b]

c = np.empty([0,matrix[0].shape[1]])

for v in matrix:
    c = np.append(c, v, axis=0)

输出:

[[8. 3. 1.]
 [2. 5. 1.]
 [6. 5. 2.]
 [2. 5. 1.]
 [2. 5. 2.]]

1
重复使用 concatenate 会导致速度变慢。在循环时请使用列表追加。 - hpaulj
我把你的评论转化为了一个答案,希望你不介意 :) - Joe
@Manuel,当在for循环中使用np.append()np.concatenate()时,它们都很慢,因为它们在幕后执行的基本上是相同的操作。 - Joe

0
如果您有一个大小为(40, 2)的数组a和一个大小为(175,2)的数组b,您可以使用np.concatenate([a,b])简单地得到一个最终大小为(215, 2)的数组。

我知道。问题是我只有一个数组,没有两个。变量 data_transform 在每次循环中都会改变。 - Luis Miguel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接