Python 中配对列表的随机样本

Random sample of paired lists in Python

我有两个列表 xy,长度都是 nxiyi 成对。我如何在保留配对信息的同时从这两个列表中随机抽取 m 值(例如 x[10] 和 y[10] 将在结果样本中在一起)

我的初步想法是这样的

代码看起来像这样。

templist = list()
for tup in zip(x, y):
    templist.append(tup)
random.shuffle(templist)
x_sub = [a for a, b in templist[0:m]]
y_sub = [b for a, b in templist[0:m]]

这对我来说似乎有点笨拙。有什么方法可以使它更清晰、简洁或 Pythonic 化吗?

如果你有两个列表,其中的元素是直接成对的,并且只是 zip 它们(在 python 3 中,将该对象转换为 list),那么使用 random.sample 取样。

>>> m = 4
>>> x = list(range(0, 3000, 3))
>>> y = list(range(0, 2000, 2))
>>> random.sample(list(zip(x, y)), m)
[(2145, 1430), (2961, 1974), (9, 6), (1767, 1178)]

如果您有两个相同维度的列表,您只想对这些元素的一个子集进行采样并将结果配对。

x = [1,2,3,4,5] 
y = [6,7,8,9,10]
sample_size = 3
idx = np.random.choice(len(x), size=sample_size, replace=False)
pairs = [(x[n], y[n]) for n in idx]
>>> pairs
[(5, 10), (2, 7), (1, 6)]

您可以对 m 对进行采样,然后使用以下代码将它们分成两个列表:

import random

x = list(range(1, 10))
y = list("abcdefghij")
m = 3

x_sub, y_sub = zip(*random.sample(list(zip(x, y)), m))

您可以实施 random_product itertools 配方。我将使用第三方库 more_itertools 为我们实现此配方。通过 pip install more_itertools.

安装这个库

代码

import more_itertool as mit


x, y, m = "abcdefgh", range(10), 2

iterable = mit.random_product(x, y, repeat=m) 

结果

iterable
# ('e', 9, 'f', 3)

不清楚 OP 想要结果的形式,但是您可以将 xy 组合在一起,例如[(x[0], y[0]), (x[1], y[1]), ...]:

paired_xy = list(zip(*[iter(iterable)]*2))
paired_xy
# [('e', 9), ('f', 3)]

另请参阅 more_itertools.sliced and more_itertools.grouper 以对连续项目进行分组。

或者,您可以 zip 进一步分组到 xy,例如[(x[0], x[1], ...), (y[0], y[1], ...)]:

paired_xx = list(zip(*paired_xy))
paired_xx
# [('e', 'f'), (9, 3)]

请注意,此方法接受任意数量的可迭代对象,xyz

# Select m random items from multiples iterables, REF 101
x, y, m = "abcdefgh", range(10), 2
a, b, c = "ABCDE", range(10, 100, 10), [False, True]
iterable = mit.random_product(x, y, a, b, c, repeat=m) 
iterable
# ('d', 6, 'E', 80, True, 'a', 1, 'D', 50, False)

详情

来自itertools recipes:

def random_product(*args, repeat=1):
    "Random selection from itertools.product(*args, **kwds)"
    pools = [tuple(pool) for pool in args] * repeat
    return tuple(random.choice(pool) for pool in pools)

我们可以看到该函数确实接受多个参数,每个参数都成为池的集合。池的大小按 repeat 关键字的值缩放。从每个池中随机选择并组合在一起作为最终结果。

另请参阅 more_itertools docs 了解更多工具。