是否有一种 Pythonic 方法可以从列表或 numpy 数组中采样 N 个连续元素

时间:2021-01-27 02:18:32

标签: python numpy sample

是否有一种 Pythonic 的方法可以从列表或 numpy 数组中选择 N 个连续的元素。

假设:

Choice = [1,2,3,4,5,6] 

我想通过随机选择 Choice 中的元素 X 以及选择后的 N-1 个连续元素来创建一个长度为 N 的新列表。

如果:

X = 4 
N = 4

结果列表将是:

Selection = [5,6,1,2] 

我认为类似于以下内容的方法会起作用。

S = [] 
for i in range(X,X+N):
    S.append(Selection[i%6])    

但我想知道是否有一个 python 或 numpy 函数可以更有效地一次选择元素。

5 个答案:

答案 0 :(得分:10)

使用 itertools,特别是 islicecycle

start = random.randint(0, len(Choice) - 1)
list(islice(cycle(Choice), start, start + n))

cycle(Choice) 是一个无限序列,它重复您的原始列表,因此切片 start:start + n 将在必要时换行。

答案 1 :(得分:4)

您可以使用列表推导式,对索引使用模运算以将其保持在列表范围内:

Choice = [1,2,3,4,5,6] 
X = 4 
N = 4
L = len(Choice)
Selection = [Choice[i % L] for i in range(X, X+N)]
print(Selection)

输出

[5, 6, 1, 2]

注意,如果N小于等于len(Choice),可以大大简化代码:

Choice = [1,2,3,4,5,6] 
X = 4 
N = 4
L = len(Choice)
Selection = Choice[X:X+N] if X+N <= L else Choice[X:] + Choice[:X+N-L]
print(Selection)

答案 2 :(得分:3)

由于您要求最有效的方法,因此我创建了一个小基准来测试此线程中提出的解决方案。

我将您当前的解决方案重写为:

def op(choice, x):
    n = len(choice)
    selection = []
    for i in range(x, x + n):
        selection.append(choice[i % n])
    return selection

其中 choice 是输入列表,x 是随机索引。

如果 choice 包含 1_000_000 个随机数,结果如下:

chepner: 0.10840400000000017 s
nick: 0.2066781999999998 s
op: 0.25887470000000024 s
fountainhead: 0.3679908000000003 s

完整代码

import random
from itertools import cycle, islice
from time import perf_counter as pc
import numpy as np


def op(choice, x):
    n = len(choice)
    selection = []
    for i in range(x, x + n):
        selection.append(choice[i % n])
    return selection


def nick(choice, x):
    n = len(choice)
    return [choice[i % n] for i in range(x, x + n)]


def fountainhead(choice, x):
    n = len(choice)
    return np.take(choice, range(x, x + n), mode='wrap')


def chepner(choice, x):
    n = len(choice)
    return list(islice(cycle(choice), x, x + n))


results = []
n = 1_000_000
choice = random.sample(range(n), n)
x = random.randint(0, n - 1)

# Correctness
assert op(choice, x) == nick(choice,x) == chepner(choice,x) == list(fountainhead(choice,x))

# Benchmark
for f in op, nick, chepner, fountainhead:
    t0 = pc()
    f(choice, x)
    t1 = pc()
    results.append((t1 - t0, f))

for t, f in sorted(results):
    print(f'{f.__name__}: {t} s')

答案 3 :(得分:3)

如果使用 numpy 数组作为源,我们当然可以使用 numpy “花式索引”。

因此,如果ChoiceArray 是列表numpyChoice 数组,并且如果Llen(Choice)len(ChoiceArray)

Selection = ChoiceArray [np.arange(X, N+X) % L]

答案 4 :(得分:2)

这是一种 event.description 方法:

numpy

即使 import numpy as np Selection = np.take(Choice, range(X,N+X), mode='wrap') 是 Python 列表而不是 Choice 数组也能工作。