Нарисуйте указанное количество образцов из списка. Использовать все элементы списка - PullRequest
2 голосов
/ 03 мая 2020

У меня есть список элементов. Теперь я хочу указать количество розыгрышей / образцов, которые я беру из этого списка. Однако я должен убедиться, что

(i) все образцы вместе включают все оригинальные элементы

(ii) размеры образцов не должны быть одинаковыми для каждого образца

Одно обновление к моему первоначальному вопросу

ОБНОВЛЕНИЕ (iii) минимальный размер выборки составляет 2

Пример:

list = [1,2,3,4,5,6,7,8,9,10]
draws = 4
samples = some_function(draws,list)
set(tuple(row) for row in sample) == set(list) # must be true

samples =[[1,2,3],[4,5],[6,7,8],[9,10]] # 4 др aws, вместе включают все элементы, два разных размера выборки, минимальный размер выборки> 2

Вопрос: есть ли простой способ сделать это, например, numpy.random? **

Вот одна попытка с использованием np.random.permutation и np.random.choice. Однако этот подход не всегда имеет все элементы списка в окончательных выборках.

srch_list = list(range(100))
draws = 10
mid = round(len(srch_list)/draws)
n_leafs = range(mid-2,mid+3)

rnd_list = np.random.permutation(srch_list)
leafs = []
for i in range(draws):
    idx = np.random.choice(n_leafs)
    leafs.append(rnd_list[:idx])
    rnd_list = rnd_list[idx:]


Ответы [ 3 ]

1 голос
/ 03 мая 2020

Один из способов сделать это:

import numpy as np

np.random.seed(1)

l = [1,2,3,4,5,6,7,8,9,10]

ids = np.concatenate(([0],
                     np.random.choice(range(1, len(l)-1), 3, replace=False),
                     [len(l)]))

ids = np.sort(ids)

chunks = [l[i:j] for i,j in zip(ids[:-1], ids[1:])]

chunks
[[1, 2], [3], [4, 5, 6, 7, 8], [9, 10]]

Теперь, если вам также нужно перетасовать элементы списка, вы можете использовать numpy .random.shuffle :

np.random.shuffle(l)
chunks = [l[i:j] for i,j in zip(ids[:-1], ids[1:])]

chunks
[[5, 9], [3], [10, 1, 6, 8, 7], [2, 4]]
0 голосов
/ 03 мая 2020

Основываясь на первом ответе (FBruzzesi), я нашел следующее решение:

def _sample_leaf_combinations(l:list,draws=10, minchunk=2):

    ldraw = list(range(minchunk,len(l)-1)[::minchunk])[:-1] # list to draw indices from. Note: deletes some items in order to ensure that distance between indices is at least minchunk
    if len(ldraw) <= draws -1:
        raise ValueError(f"Cannot make {draws} draws from list of {len(l)} with minchunk of {minchunk}. Consider lowering minchunk")


    ids = np.concatenate(([0],np.random.choice(ldraw, draws-1, replace=False),[len(l)]))
    ids = np.sort(ids)
    chunks = [l[i:j] for i,j in zip(ids[:-1], ids[1:])]

    return chunks

Спасибо за помощь!

0 голосов
/ 03 мая 2020

Вот еще одно решение:

import numpy as np


def draw_samples(pool, nsamples, min_sample_size=1):
    # make sure pool is an array for the logic to work
    if not isinstance(pool, np.ndarray):
        pool = np.array(pool)

    # fist determine the total amount of samples to be drawn from pool
    min_total_n_elements = len(pool) if len(pool) > nsamples*min_sample_size \
        else nsamples*min_sample_size
    max_total_n_elements = min_total_n_elements + 5  # the sky is the limit
    total_n_elements = np.random.randint(
        min_total_n_elements, max_total_n_elements
    )
    additional_n_elements = total_n_elements - min_total_n_elements

    # then extend the pool the samples are going to be drawn from
    extended_pool = np.append(
        pool, np.random.choice(pool, size=additional_n_elements)
    ) if additional_n_elements else pool

    # assign each element in the pool to a sample
    assignment = np.array(list(np.arange(nsamples))*min_sample_size)
    if total_n_elements - len(assignment):
        assignment = np.append(
            assignment, np.random.choice(
                np.arange(nsamples), size=total_n_elements - len(assignment)
            )
        )
    np.random.shuffle(assignment)
    samples = [extended_pool[assignment == i] for i in range(nsamples)]

    return samples


lst = np.arange(10)
n_subsamples = 4
samples = draw_samples(lst, n_subsamples, min_sample_size=2)
print(set.union(*[set(sample) for sample in samples]) == set(lst))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...