在numpy中随机选择不同的集合?

2024-10-19 16:36:08 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图在numpy中随机选择一组整数,但遇到了一个奇怪的错误。如果我定义了一个具有两组不同大小的numpy数组,np.random.choice在它们之间进行选择而不会出现问题:

Set1 = np.array([[1, 2, 3], [2, 4]])
In:  np.random.choice(Set1)
Out: [4, 5]

但是,一旦numpy数组是相同大小的集合,我就会得到一个值错误:

Set2 = np.array([[1, 3, 5], [2, 4, 6]])
In:   np.random.choice(Set2)
ValueError: a must be 1-dimensional    

可能是用户错误,但我已经检查了好几次,唯一的区别是集合的大小。我意识到我可以做如下事情:

Chosen = np.random.choice(N, k)
Selection = Set[Chosen]

其中N是集合的数量k是样本的数量,但我只是想知道是否有更好的方法,特别是当集合大小相同时,我在做什么错误来引发值错误

打印出的Set1Set2供参考:

In: Set1
Out: array([list([1, 3, 5]), list([2, 4])], dtype=object)
In: type(Set1)
Out: numpy.ndarray

In: Set2
Out: 
array([[1, 3, 5],
       [2, 4, 6]])
In: type(Set2)
Out: numpy.ndarray

Tags: innumpy数量type错误nprandom数组
1条回答
网友
1楼 · 发布于 2024-10-19 16:36:08

您的问题是由于对numpy阵列工作原理的误解造成的。第一个示例无法“真正”转换为数组,因为numpy不支持不规则数组。最终将得到一个指向两个python列表的对象引用数组。第二个例子是一个合适的2xN数值数组。我可以想到两种解决方案

显而易见的方法(顺便说一句,这两种情况都适用)是选择索引而不是子列表。由于您是使用替换进行采样,因此只需生成索引并直接使用它即可:

Set[np.random.randint(N, size=k)]

这和

Set[np.random.choice(N, k)]

如果您想选择不替换,那么最好使用^{}replace=False。这类似于洗牌,但效率不如洗牌。在任何一种情况下,都可以为索引编写一行:

Set[np.random.choice(N, k, replace=False)]

或:

index = np.arange(Set.shape[0])
np.random.shuffle(index)
Set[index[:k]]

不过^{}的好处在于,您可以直接将它应用于Set,无论它是一维数组还是多维数组。洗牌将始终沿第一个轴进行,因此您可以在之后只取顶部的k元素:

np.random.shuffle(Set)
Set[:k]

洗牌操作只在适当的地方起作用,所以你必须把它写出来。对于大型阵列,它的效率也较低,因为无论k有多小,都必须预先创建整个范围

另一个解决方案是将第二个示例转换为与第一个示例类似的列表对象数组。我不推荐这种解决方案,除非您使用numpy的唯一原因是choice函数。事实上,我根本不推荐它,因为此时您可以而且可能应该使用pythons标准^{}模块。撇开免责声明不谈,您可以强制第二个数组的数据类型为object。它将消除使用numpy的任何好处,并且不能直接完成。简单地设置dtype=object仍然会创建一个2D数组,但会在其中存储对python int对象的引用,而不是原语。你必须这样做:

Set = np.zeros(N, dtype=object)
Set[:] = [[1, 2, 3], [2, 4]]

现在您将获得一个与第一个示例中的对象基本相同的对象,因此可以直接应用np.random.choice

注意

我在这里展示了遗留的^{}方法,这是因为个人惯性。正如我链接到的文档中所建议的那样,正确的方法是使用新的GeneratorAPI。对于^{}方法尤其如此,它在新的实现中效率更高。使用不再困难:

Set[np.random.default_rng().choice(N, k, replace=False)]

还有其他优势,例如您现在可以直接选择,甚至可以从多维数组中选择:

np.random.default_rng().choice(Set2, k, replace=False)

对于^{}也是如此,它与choice一样,现在允许您选择要重新排列的轴:

np.random.default_rng().shuffle(Set)
Set[:k]

相关问题 更多 >