web-dev-qa-db-ja.com

Pythonに整数のランダムリストを作成します

テスト目的で整数のランダムリストを作成したいと思います。数字の分布は重要ではありません。カウントしているのはtimeだけです。乱数の生成は時間のかかる作業ですが、もっと良い方法が必要です。

私の現在のソリューションは次のとおりです。

import random
import timeit

# Random lists from [0-999] interval
print [random.randint(0, 1000) for r in xrange(10)] # v1
print [random.choice([i for i in xrange(1000)]) for r in xrange(10)] # v2

# Measurement:
t1 = timeit.Timer('[random.randint(0, 1000) for r in xrange(10000)]', 'import random') # v1
t2 = timeit.Timer('random.sample(range(1000), 10000)', 'import random') # v2

print t1.timeit(1000)/1000
print t2.timeit(1000)/1000

v2はv1よりも高速ですが、このような大規模では機能していません。次のエラーが発生します。

ValueError:母集団より大きいサンプル

その規模で機能する高速で効率的なソリューションはありますか?

答えからいくつかの結果

アンドリュース:0.000290962934494

ニブラー:0.0058455221653

ケニーTM:0.00219276118279

NumPyが来て、見て、征服しました。

68
Stiggo

あなたが望むものが完全に明確ではありませんが、私は numpy.random.randint を使用します:

import numpy.random as nprnd
import timeit

t1 = timeit.Timer('[random.randint(0, 1000) for r in xrange(10000)]', 'import random') # v1

### Change v2 so that it picks numbers in (0, 10000) and thus runs...
t2 = timeit.Timer('random.sample(range(10000), 10000)', 'import random') # v2
t3 = timeit.Timer('nprnd.randint(1000, size=10000)', 'import numpy.random as nprnd') # v3

print t1.timeit(1000)/1000
print t2.timeit(1000)/1000
print t3.timeit(1000)/1000

私のマシンに与える:

0.0233682730198
0.00781716918945
0.000147947072983

Randintはrandom.sampleとはvery異なることに注意してください(あなたのケースで動作するためには、1,000から10,000をコメンテーターは指摘しました-あなたが本当に0から1,000までそれらを望むなら、10で割ることができます)。

そして、あなたがどの分布を得ているのか本当に気にしないなら、あなたはあなたの問題をあまりよく理解していないか、または乱数である可能性があります。

60
Andrew Jaffe

すべてのランダムメソッドはrandom.random()を呼び出すことになります。そのため、最良の方法は直接呼び出すことです。

[int(1000*random.random()) for i in xrange(10000)]

例えば、

  • random.randintrandom.randrangeを呼び出します。
  • random.randrangeには、istart + istep*int(self.random() * n)を返す前に範囲をチェックするためのオーバーヘッドがあります。

もちろん、NumPyははるかに高速です。

30
John La Rooy

パフォーマンスに関するあなたの質問は重要ではありません。両方の機能は非常に高速です。コードの速度は、乱数を使用してdoで決定されます。

ただし、これら2つの関数のbehaviourの違いを理解することが重要です。 1つは置換ありでランダムサンプリングを行い、もう1つは置換なしでランダムサンプリングを行います。

5
Colonel Panic

まず、randrange(0,1000)ではなく、randint(0,999)またはrandint(0,1000)を使用する必要があります。 randintの上限は包括的です。

効率的には、randintrandrangeを呼び出すrandomの単なるラッパーなので、randomを使用するだけです。また、xrangeではなく、sampleの引数としてrangeを使用します。

使用できます

[a for a in sample(xrange(1000),1000) for _ in range(10000/1000)]

sampleを使用して範囲内で10,000個の数値を10回生成します。

(もちろん、これはNumPyに勝るものではありません。)

$ python2.7 -m timeit -s 'from random import randrange' '[randrange(1000) for _ in xrange(10000)]'
10 loops, best of 3: 26.1 msec per loop

$ python2.7 -m timeit -s 'from random import sample' '[a%1000 for a in sample(xrange(10000),10000)]'
100 loops, best of 3: 18.4 msec per loop

$ python2.7 -m timeit -s 'from random import random' '[int(1000*random()) for _ in xrange(10000)]' 
100 loops, best of 3: 9.24 msec per loop

$ python2.7 -m timeit -s 'from random import sample' '[a for a in sample(xrange(1000),1000) for _ in range(10000/1000)]'
100 loops, best of 3: 3.79 msec per loop

$ python2.7 -m timeit -s 'from random import shuffle
> def samplefull(x):
>   a = range(x)
>   shuffle(a)
>   return a' '[a for a in samplefull(1000) for _ in xrange(10000/1000)]'
100 loops, best of 3: 3.16 msec per loop

$ python2.7 -m timeit -s 'from numpy.random import randint' 'randint(1000, size=10000)'
1000 loops, best of 3: 363 usec per loop

しかし、あなたは数字の分布を気にしないので、なぜ単に使用しないのですか:

range(1000)*(10000/1000)

2
kennytm