7章では、NumPyの『乱数(rand, random_sample, randint, randn, normal)』『random.choice()によるデータの抽出』『乱数のシード』について解説します。
データ分析においてよく使われる乱数生成の関数を一覧表付きで網羅的に解説していますので、ぜひ最後までご覧ください!
本連載講座【Python ライブラリ編】では、データサイエンスに必要なPythonライブラリやその使い方を基礎から学ぶことができます。
NumPy・Pandas・Matplotlib・Scipy・Seabornについて、初学者の方にも分かりやすいよう丁寧に解説しています。
さらに、学習した内容を定着させられるように各章に演習問題を用意しています。
・Pythonでデータ分析ができるようになりたい
・Pythonの基礎事項は一通り学んだので、さらに深く学びたい
このように考えている方はTech Teacherが運営する【Python ライブラリ編】で、Pythonによるデータサイエンスの学習をすることをお勧めします!
なお、『Pythonについて全く知らない』・『Pythonの基礎事項がまだ分かっていない』という方は、まずコチラの【Python 基礎編】で基礎を一通り学習してからライブラリ編に取り掛かりましょう!
<ライブラリ編 目次>
<ライブラリの基礎>
1章:ライブラリとは
<NumPy>
2章:NumPyの概要と配列(ndarray)
3章:統計量や次元の取得/ソート
4章:配列のインデックス
5章:numpy.whereによる条件制御
6章:配列の結合/分割
7章:乱数
<SciPy>
8章:SciPyの概要と基本操作
<Pandas>
9章:SeriesとDataFrame/統計量の取得
10章:データの読み込み/書き込み
11章:データの取り出し/追加
12章:データのソート
13章:データの結合
14章:階層型インデックス
15章:groupbyによる集計
16章:マッピング処理
17章:欠損値の扱い
<Matplotlib>
18章:Matplotlibの概要
19章:pyplotインターフェース
20章:オブジェクト指向インターフェース
<Seaborn>
21章:Seabornの概要と基本操作
乱数とは
『乱数』とは、簡単に言うとランダムな数のことです。
例えば、サイコロを投げると1~6までの整数が完全にランダムで出現します。
そのため、サイコロの出目は乱数であると言うことができます。
NumPyでは、randomモジュールを用いることで様々な種類の乱数(正確には疑似乱数)を簡単に生成することができます。
乱数の種類と生成する関数
下表は、NumPyのrandomモジュールで生成できる主な乱数とそれらを生成する関数をまとめたものです。
関数 | 乱数が従う分布 |
---|---|
rand | 0.0以上1.0未満の一様分布 |
random_sample | 0.0以上1.0未満の一様分布 |
randint | 指定した範囲の一様分布(整数) |
randn | 平均0, 標準偏差1の正規分布 |
normal | 指定した平均, 標準偏差の正規分布 |
なお、一様分布や正規分布については以下の記事で詳しく解説しております。
いずれも基本的な確率分布なので、不安な方はぜひ参照してください!
rand
『rand()』関数は、0.0以上1.0未満の一様分布に従う浮動小数点数の乱数を返します。
rand関数の引数の指定方法は以下の通りです。
・1次元配列の場合
np.random.rand(乱数の個数)
・多次元配列の場合
np.random.rand(1次元目の大きさ, 2次元目の大きさ, …)
では、実行例で確認してみましょう。
#0.0以上1.0未満の一様分布
x = np.random.rand(5)
print(x)
[0.55979423 0.81157485 0.89541704 0.11013642 0.50571754]
多次元配列を生成する場合は、各次元の大きさを引数として指定します。
#2×3の配列を生成する場合
y = np.random.rand(2, 3)
print(y)
[[0.14035342 0.37442591 0.16631856]
[0.3992503 0.92944745 0.79290582]]
random_sample
『random_sample()』関数はrand関数と同様に、0.0以上1.0未満の一様分布に従う浮動小数点数の乱数を返します。
random_sample関数の引数の指定方法は以下の通りです。
np.random.random_sample(配列の形状を表すタプル)
rand関数との違いは、配列の形状をタプルで指定するという点です。
なお、1次元配列の場合はタプルでなく整数を引数として指定することも可能です。
#0.0以上1.0未満の一様分布
x = np.random.random_sample(5)
print(x)
[0.08784795 0.54047262 0.04248919 0.94589097 0.71673511]
#2×3の配列を生成する場合
y = np.random.random_sample((2, 3))
print(y)
[[0.14581083 0.33595846 0.8615866 ]
[0.6114845 0.53356767 0.78485187]]
randint
『randint()』関数は、引数で指定した範囲内で一様分布に従う整数の乱数を返します。
randint関数の引数の指定方法は以下の通りです。
np.random.randint(下限, 上限, 配列の形状)
第一引数で下限、第二引数で上限、第三引数で配列の形状を指定します。
#50以上100未満の整数を5つ生成
x = np.random.randint(50, 100, 5)
#-10以上10未満の整数を3×4の配列で生成
y = np.random.randint(-10, 10, (3,4))
print(x)
print(y)
[59 62 68 52 54]
[[-7 8 -7 1]
[ 0 1 3 8]
[ 8 1 -5 9]]
なお、引数として整数(Nとする)を1つだけ指定した場合、0以上N未満の整数を1つだけ返します。
#0以上1000未満の整数を1つだけ生成
print(np.random.randint(1000))
308
randn
『randn()』関数は、平均0, 標準偏差1の正規分布に従う浮動小数点数の乱数を返します。
randn関数の引数の指定方法は以下の通りです。
・1次元配列の場合
np.random.randn(乱数の個数)
・多次元配列の場合
np.random.randn(1次元目の大きさ, 2次元目の大きさ, …)
引数の指定方法はrand関数と同じです。
#0.0以上1.0未満の正規分布
x = np.random.randn(10)
print(x)
[ 0.72101398 1.57753075 0.01538328 -1.34453128 0.67869597 -1.88376924
-1.37671326 0.43310617 0.07320538 1.06401262]
多次元配列もrand関数と同様の方法で取得することができます。
#2×3の配列を生成する場合
y = np.random.randn(2, 3)
print(y)
[[-1.52209929 -1.69464664 1.50052544]
[ 0.62950238 0.59665093 -0.75334204]]
normal
『normal()』関数は、指定した平均・標準偏差の正規分布に従う浮動小数点数の乱数を返します。
normal関数の引数の指定方法は以下の通りです。
np.random.normal(平均, 標準偏差, 配列の形状)
第一引数で正規分布の平均、第二引数で標準偏差、第三引数で配列の形状を指定します。
#平均100, 標準偏差10の正規分布
x = np.random.normal(100, 10, 5)
print(x)
[ 95.78584941 120.17366124 108.01494689 100.85792458 101.62315476]
#平均50, 標準偏差10の正規分布に従う2×3の配列を生成
y = np.random.normal(50, 10, (2,3))
print(y)
[[37.17746251 53.81397604 63.23320681]
[52.42286056 39.38134457 58.53463845]]
random.choice()によるデータのランダム抽出
『random.choice()』関数を用いると、配列から要素をランダムに抽出することができます。
random.choice()関数の書式は以下の通りです。
np.random.choice(配列, 形状, 重複の許可・不許可, 各要素の出現確率)
第一引数で元の配列、第二引数で取り出したときの形状(タプル)、第三引数で重複の許可・不許可、第四引数で配列の各要素の出現確率を設定します。
第三引数はTrueまたはFalseで指定し、省略した場合はTrue(重複あり)が適用されます。
第四引数では各要素の出現確率をリストで指定します。省略した場合、すべての要素が等確率で出現します。
それでは、実行例を見てみましょう。
x = np.array([1,2,3,4,5,6])
#xからランダムに10個抽出(重複あり)
x_cho = np.random.choice(x, 10)
#xからランダムに2×3個抽出(重複あり)
x_cho_arr = np.random.choice(x, (2,3))
print(x_cho)
print(x_cho_arr)
[2 6 1 6 6 6 4 2 4 1]
[[6 1 3]
[6 4 1]]
第三引数をFalseとすると、重複なしで抽出が行われます。
このとき、抽出する個数がもとの配列の要素数を超えると正しく実行できません。
x = np.array([1,2,3,4,5,6])
#xからランダムに6個抽出(重複なし)
x_cho = np.random.choice(x, 6, replace=False)
print(x_cho)
[2 4 1 5 3 6]
第四引数にリストを渡して各要素の出現確率を指定することができます。
x = np.array([1,2,3,4,5,6])
#xからランダムに10個抽出(重複なし, 確率を指定)
x_cho = np.random.choice(x, 10, p=[0.1, 0.1, 0.1, 0.1, 0.1, 0.5])
print(x_cho)
[4 6 6 6 1 4 6 6 6 6]
確かに6が出る確率が他と比べて高くなっていることが分かります。
また、第一引数に配列ではなく0以上の整数値を渡すと、0以上指定した値未満の整数の配列から抽出が行われます。
#0以上100未満の整数配列から10個抽出
a = np.random.choice(100, 10)
print(a)
[37 25 77 72 9 20 80 69 79 47]
シードについて
ここまで紹介した乱数はすべてコンピューターで生成される疑似乱数と呼ばれるものであり、真の乱数とは異なります。
疑似乱数を生成する際に初期値をもとに計算を行うのですが、np.random.seed()を用いることでその初期値を自分で設定できます。
シード値を設定すると乱数生成の初期値が固定され、異なる環境でも毎回同じ結果が返ってくるようになります。
では実際に、シード値を0として以下のコードを実行してみましょう。
#シード値を設定
np.random.seed(0)
#平均0, 標準偏差1の正規分布に従う数を10個取得
x = np.random.randn(10)
print(x)
[ 1.76405235 0.40015721 0.97873798 2.2408932 1.86755799 -0.97727788
0.95008842 -0.15135721 -0.10321885 0.4105985 ]
みなさんの環境でもこの実行例と同じような結果が得られたと思います。
シード値の設定は、データ分析において一貫性を担保したり、ソースコードを他人と共有した時に実行結果が変わらないようにするなどの目的で行われます。
『Tech Teacher』3つの魅力
魅力1. オーダーメイドのカリキュラム
『Tech Teacher』では、決められたカリキュラムがなくオーダーメイドでカリキュラムを組んでいます。「質問だけしたい」「相談相手が欲しい」等のご要望も実現できます。
魅力2. 担当教師によるマンツーマン指導
Tech Teacherでは、完全マンツーマン指導で目標達成までサポートします。
東京大学を始めとする難関大学の理系学生・院生・博士の教師がが1対1で、丁寧に指導しています。
そのため、理解できない箇所は何度も分かるまで説明を受けることができます。
魅力3. 3,960円/30分で必要な分だけ受講
Tech Teacherでは、授業を受けた分だけ後払いの「従量課金制」を採用しているので、必要な分だけ授業を受講することができます。また、初期費用は入会金22,000円のみです。一般的なプログラミングスクールとは異なり、多額な初期費用がかからないため、気軽に学習を始めることができます。
まとめ
・魅力1. 担当教師によるマンツーマン指導
・魅力2. オーダーメイドのカリキュラム
・魅力3. 3,960円/30分で必要な分だけ受講
質問のみのお問い合わせも受け付けております。
7章の練習問題
以下の練習問題を解いてみましょう。
練習問題
問1. 以下の(1)~(4)を求めて出力してください。ただし、各問のプログラムの初めで、np.random.seed()を用いてシード値を0に設定してから実行するようにしてください。
(1) 0.0以上1.0未満の一様分布から10個の浮動小数点数を取り出した1次元配列
(2) 0以上100未満の整数の一様分布から値を取り出した2×3の配列
(3) 平均0、標準偏差1の正規分布から10個の浮動小数点数を取り出した1次元配列
(4) (3)で生成した配列から8個の要素を重複を許して取り出した1次元配列
問2(応用編). 「0以上1未満の一様分布から値を1つずつ取り出していくとき、総和が1になるまでに取り出した回数n」を求める操作を100000回繰り返し、100000回の試行におけるnの平均を出力してください。ただし、シード値は0とします。
解答
(1)
#(1)
np.random.seed(0)
x1 = np.random.rand(10)
print(x1)
[0.5488135 0.71518937 0.60276338 0.54488318 0.4236548 0.64589411
0.43758721 0.891773 0.96366276 0.38344152]
(2)
#(2)
np.random.seed(0)
x2 = np.random.randint(100)
print(x2)
44
(3)
#(3)
np.random.seed(0)
x3 = np.random.randn(10)
print(x3)
[ 1.76405235 0.40015721 0.97873798 2.2408932 1.86755799 -0.97727788
0.95008842 -0.15135721 -0.10321885 0.4105985 ]
(4)
#(4)
np.random.seed(0)
x4 = np.random.choice(x3, 8)
print(x4)
[-0.97727788 1.76405235 2.2408932 2.2408932 -0.15135721 0.4105985
2.2408932 -0.97727788]
N = 100000 #試行回数
n_ave = 0 #取り出した回数の平均値
np.random.seed(0) #シード値の設定
for i in range(N):
temp_sum = 0 #累積和
n = 0 #取り出した回数
#総和が1を超えるまで取り出す
while temp_sum <= 1:
temp_sum += np.random.rand()
n += 1
n_ave += n
#平均値を計算(取り出した回数の合計を試行回数で割る)
n_ave /= N
print(n_ave)
2.71626
ちなみにこのようにして求めた値は、試行回数を大きくすると自然対数の底e(=2.718…)に近づくということが知られています。
次のページへ