python - 如何将原语列表附加到 numpy 对象数组
问题描述
编辑:关于如何不这样做以及如何找到替代方案,我已经获得了很多有用的反馈,但使其有用取决于我的用例的特质,这会使这个问题对其他人不太有用。在这一点上,我不是在寻找使用这种结构的数据的替代方法。我正在寻找为什么在 numpy 中似乎不可能做到这一点(或者如果不是不可能的话怎么做)
我有一个 numpy 数组,看起来像
a = array([list([1]), list([4, 5])], dtype=object)
我想附加一个列表,如
b = [2, 3, 4]
得到类似的结果
array([list([1]), list([4, 5]), list([2, 3, 4])], dtype=object)
但是,我尝试过的每种方法都产生了:
array([list([1]), list([4, 5]), 2, 3, 4], dtype=object)
我尝试过 vstack、连接和追加,以及将东西包装在列表或 ndarray 中。
我为什么要这样做?基本上,我在 ndarray 中有很多数据将被输入 sklearn。我想要一个 3d ndarray(数据集 x 数据点 x 特征),但是传入的数据很糟糕,并且某些东西有不同的长度,所以最里面的维度必须是列表。我正在尝试附加一个派生功能,但一直失败。我已经设法重新排序操作以避免需要执行此附加操作,但我仍然想知道该怎么做。对于 numpy 来说,这似乎是一个奇怪的失败。编辑:简而言之,外部数组必须是ndarray,因为它实际上是2d,并且经常使用复杂的切片,而追加操作很少发生。
解决方案
首先附加到数组是一项昂贵且通常很臭的操作。问题是数组的内容可能是可变的,但底层缓冲区的地址不是。每次你追加一个元素时,整个东西都会被重新分配和复制。据我所知,甚至没有像list
.
如果您准备采用稍微不同的方法,我建议您list
像现在一样维护您的数据。只要您真正需要数组,您只需将列表转换为数组。请记住,这比每次都重新分配到一个新数组要便宜,而且与追加的数量相比,您可能不必经常这样做:
stack = [[1], [4, 5]]
a = np.array(stack, dtype=np.object)
# do stuff to the array
...
stack.append([2, 3, 4])
a = np.array(stack, dtype=np.object)
了解您的问题后立即更新
如果您的目标只是弄清楚如何将元素附加到对象数组而不妨碍它是一个列表的事实,那么您必须首先创建一个空数组或元素。我建议不要像某些评论所建议的那样尝试使用假元素强制类型,而是只创建空元素并将它们显式设置到您的列表中。如果您想要一个干净的界面,您可以将操作包装在一个函数中。
这是一个例子:
b = [2, 3, 4]
c = np.empty(1, dtype=np.object)
c[0] = b
a = np.concatenate((a, c))
或者
a = np.append(a, c)
当然这不如np.array([b], dtype=np.object)
. 您几乎必须这样做的原因是 numpy 将列表或元组的任何内容视为您要在外部级别转换为数组的特殊项目。