您对[] 和np.append 的使用表明您正在尝试用数组模仿常见的列表追加模型。您至少阅读了足够多的 np.append 文档,知道您需要使用 axis,并且它返回一个新数组(文档很清楚这是一个副本)。
但是您是否通过一个小示例测试了这个想法,并实际查看结果(逐步)?
In [326]: rows = []
In [327]: rows = np.append(rows, np.arange(3), axis=0)
In [328]: rows
Out[328]: array([0., 1., 2.])
In [329]: rows.shape
Out[329]: (3,)
第一个追加不做任何事情 - 结果与arange(3) 相同。
In [330]: rows = np.append(rows, np.arange(3), axis=0)
In [331]: rows
Out[331]: array([0., 1., 2., 0., 1., 2.])
In [332]: rows.shape
Out[332]: (6,)
你明白为什么吗?我们在轴 0 上加入 2 个 1d 数组,形成 1d。
以[]为起点与从这个数组开始是一样的:
In [333]: np.array([])
Out[333]: array([], dtype=float64)
In [334]: np.array([]).shape
Out[334]: (0,)
对于axis,np.append 只是对concatenate 的调用:
In [335]: np.concatenate(( [], np.arange(3)), axis=0)
Out[335]: array([0., 1., 2.])
np.append 排序看起来像列表追加,但它不是克隆。这实际上只是使用concatenate 的一种名称不佳的方式。如果不真正了解尺寸,您将无法正确使用它。 np.append 有一个错误示例,与您使用连接时遇到的错误非常相似。
在循环中重复使用这些数组concatenates 不是一个好主意。正如您所发现的,很难获得正确的尺寸。即使它有效,它也很慢,因为每一步都会生成一个副本(随着迭代而增长)。
这就是为什么另一个答案坚持使用列表附加。
vstack 类似于带有轴 0 的 concatenate,但它确保所有参数都是 2d。但如果数字列不同,则会引发错误:
In [336]: np.vstack(( [],np.arange(3)))
Traceback (most recent call last):
File "<ipython-input-336-22038d6ef0f7>", line 1, in <module>
np.vstack(( [],np.arange(3)))
File "<__array_function__ internals>", line 180, in vstack
File "/usr/local/lib/python3.8/dist-packages/numpy/core/shape_base.py", line 282, in vstack
return _nx.concatenate(arrs, 0)
File "<__array_function__ internals>", line 180, in concatenate
ValueError: all the input array dimensions for the concatenation axis must match exactly, but along dimension 1, the array at index 0 has size 0 and the array at index 1 has size 3
In [337]: np.vstack(( [0,0,0],np.arange(3)))
Out[337]:
array([[0, 0, 0],
[0, 1, 2]])
如果您加入的只是 (n,30) 数组的行,那么您确实知道结果的列大小。
In [338]: res = np.zeros((0,3))
In [339]: np.vstack(( res, np.arange(3)))
Out[339]: array([[0., 1., 2.]])
如果注意形状细节,可以迭代创建数组。
但是,与其一一收集行,不如创建一个mask 并收集一次。
差不多
mask = np.array([question.match(example) for example in rows])
true_rows = rows[mask]
false_rows = rows[~mask]
这仍然需要迭代,但总体上应该更快。