4

1500 個の要素を持つリスト a_tot があり、このリストをランダムに 2 つのリストに分割したいと考えています。リスト a_1 には 1300 の要素があり、リスト a_2 には 200 の要素があります。私の質問は、元のリストを 1500 要素でランダム化する最良の方法についてです。リストをランダム化すると、1300 のスライスと 200 の別のスライスを取得できます。1 つの方法は random.shuffle を使用することで、もう 1 つの方法は random.sample を使用することです。2 つの方法のランダム化の品質に違いはありますか? リスト 1 のデータは、リスト 2 のデータと同様にランダム サンプルである必要があります。推奨事項はありますか?シャッフルの使用:

random.shuffle(a_tot)    #get a randomized list
a_1 = a_tot[0:1300]     #pick the first 1300
a_2 = a_tot[1300:]      #pick the last 200

サンプルを使用して

new_t = random.sample(a_tot,len(a_tot))    #get a randomized list
a_1 = new_t[0:1300]     #pick the first 1300
a_2 = new_t[1300:]      #pick the last 200
4

6 に答える 6

4

シャッフルのソース:

def shuffle(self, x, random=None, int=int):
    """x, random=random.random -> shuffle list x in place; return None.

    Optional arg random is a 0-argument function returning a random
    float in [0.0, 1.0); by default, the standard random.random.
    """

    if random is None:
        random = self.random
    for i in reversed(xrange(1, len(x))):
        # pick an element in x[:i+1] with which to exchange x[i]
        j = int(random() * (i+1))
        x[i], x[j] = x[j], x[i]

サンプルのソース:

def sample(self, population, k):
    """Chooses k unique random elements from a population sequence.

    Returns a new list containing elements from the population while
    leaving the original population unchanged.  The resulting list is
    in selection order so that all sub-slices will also be valid random
    samples.  This allows raffle winners (the sample) to be partitioned
    into grand prize and second place winners (the subslices).

    Members of the population need not be hashable or unique.  If the
    population contains repeats, then each occurrence is a possible
    selection in the sample.

    To choose a sample in a range of integers, use xrange as an argument.
    This is especially fast and space efficient for sampling from a
    large population:   sample(xrange(10000000), 60)
    """

    # XXX Although the documentation says `population` is "a sequence",
    # XXX attempts are made to cater to any iterable with a __len__
    # XXX method.  This has had mixed success.  Examples from both
    # XXX sides:  sets work fine, and should become officially supported;
    # XXX dicts are much harder, and have failed in various subtle
    # XXX ways across attempts.  Support for mapping types should probably
    # XXX be dropped (and users should pass mapping.keys() or .values()
    # XXX explicitly).

    # Sampling without replacement entails tracking either potential
    # selections (the pool) in a list or previous selections in a set.

    # When the number of selections is small compared to the
    # population, then tracking selections is efficient, requiring
    # only a small set and an occasional reselection.  For
    # a larger number of selections, the pool tracking method is
    # preferred since the list takes less space than the
    # set and it doesn't suffer from frequent reselections.

    n = len(population)
    if not 0 <= k <= n:
        raise ValueError, "sample larger than population"
    random = self.random
    _int = int
    result = [None] * k
    setsize = 21        # size of a small set minus size of an empty list
    if k > 5:
        setsize += 4 ** _ceil(_log(k * 3, 4)) # table size for big sets
    if n <= setsize or hasattr(population, "keys"):
        # An n-length list is smaller than a k-length set, or this is a
        # mapping type so the other algorithm wouldn't work.
        pool = list(population)
        for i in xrange(k):         # invariant:  non-selected at [0,n-i)
            j = _int(random() * (n-i))
            result[i] = pool[j]
            pool[j] = pool[n-i-1]   # move non-selected item into vacancy
    else:
        try:
            selected = set()
            selected_add = selected.add
            for i in xrange(k):
                j = _int(random() * n)
                while j in selected:
                    j = _int(random() * n)
                selected_add(j)
                result[i] = population[j]
        except (TypeError, KeyError):   # handle (at least) sets
            if isinstance(population, list):
                raise
            return self.sample(tuple(population), k)
    return result

ご覧のとおり、どちらの場合も、ランダム化は基本的に行によって行われint(random() * n)ます。したがって、基本的なアルゴリズムは本質的に同じです。

于 2012-10-09T11:01:22.447 に答える
1

random.shuffle()list指定されたインプレースをシャッフルします。その長さは同じままです。

random.sample()置換nなしで指定されたシーケンスから項目を選択し (これは、 がある限り、タプルなどでもかまいません__len__())、それらをランダムな順序で返します。

于 2012-10-09T10:58:26.287 に答える
0

ランダム化は、両方のオプションで同じようにうまくいくはずです。というshuffleのは、それが何をするのかが読者にとってすぐに明確になるからです。

于 2012-10-09T10:59:24.710 に答える
0

1 つは元のリストを更新し、もう 1 つはそれを使用 (読み取り専用) することを除いて、それらはまったく同じだと思います。品質に違いはありません。

于 2012-10-09T10:57:38.063 に答える
0
from random import shuffle
from random import sample 
x = [[i] for i in range(10)]
shuffle(x)
sample(x,10)

シャッフルは同じリストで出力を更新しますが、サンプルは更新リストを返しますサンプルはpic機能で引数の数を提供しますが、シャッフルは同じ長さの入力のリストを提供します

于 2012-10-09T11:08:17.673 に答える