NumPy: Generate random numbers with np.random

Posted: | Tags: Python, NumPy

In NumPy, you can generate random numbers with the numpy.random module.

From NumPy version 1.17 onwards, it is recommended to use the Generator instance. However, legacy functions such as np.random.rand() and np.random.normal() remain available (as of version 1.26.1).

For the Python standard library's random module, refer to the following article.

The NumPy version used in this article is as follows. Note that functionality may vary between versions.

import numpy as np

print(np.__version__)
# 1.26.1

How to use numpy.random

Generator instances (Version 1.17 and Later)

First, use Generator instances, which have been recommended since version 1.17.

Basic usage

Generate a Generator instance using np.random.default_rng().

rng = np.random.default_rng()
print(rng)
# Generator(PCG64)

You can generate different types of random numbers using methods of the Generator instance.

For example, the random() method generates uniformly distributed random floating-point numbers (float) from 0.0 (inclusive) to 1.0 (exclusive).

The size argument determines the shape. The default (size=None) returns a scalar value. Specifying an integer (int) returns a one-dimensional array (ndarray), and specifying a tuple returns an array (ndarray) of that shape.

In the random() method, size is the first argument.

print(rng.random())
# 0.2281556131299135

print(type(rng.random()))
# <class 'float'>

print(rng.random(3))
# [0.3888496  0.9058742  0.74585675]

print(type(rng.random(3)))
# <class 'numpy.ndarray'>

print(rng.random((2, 3)))
# [[0.42818743 0.22573104 0.33022384]
#  [0.64782123 0.82035051 0.31118108]]

print(type(rng.random((2, 3))))
# <class 'numpy.ndarray'>

Although not shown in the example, arrays of three dimensions or more can also be generated by increasing the number of elements in the tuple.

More methods will be discussed later.

Fix the seed

You can specify any non-negative integer as a seed for np.random.default_rng(). Without specification, a different seed is used each time.

rng_1 = np.random.default_rng(1234)
print(rng_1.random())
# 0.9766997666981422

rng_2 = np.random.default_rng(1234)
print(rng_2.random())
# 0.9766997666981422

For more details on random seeds, refer to the official documentation.

Change the random number generator

np.random.default_rng() uses PCG64 as the random number generator.

To use a different random number generator than the default PCG64, employ the np.random.Generator() constructor with a BitGenerator such as MT19937 or SFC64.

You can optionally specify a seed when creating a BitGenerator. Regardless of the chosen random number generator, the same methods can be used.

rng_mt = np.random.Generator(np.random.MT19937(1234))
print(rng_mt)
# Generator(MT19937)

print(rng_mt.random())
# 0.12038356302504949

Legacy methods (RandomState instances, functions)

While Generator instances have been the recommended choice since version 1.17, legacy methods remain accessible.

These are retained for backward compatibility, so it's better to use the faster and continuously improving Generator for writing new code.

Generator and its associated infrastructure was introduced in NumPy version 1.17.0. There is still a lot of code that uses the older RandomState and the functions in numpy.random. While there are no plans to remove them at this time, we do recommend transitioning to Generator as you can. The algorithms are faster, more flexible, and will receive more improvements in the future. Random sampling (numpy.random) — NumPy v1.26 Manual

Use RandomState instances

Before the introduction of Generator, RandomState was used.

Generate an instance using np.random.RandomState() and call its various methods.

rs = np.random.RandomState()
print(rs)
# RandomState(MT19937)

print(rs.rand())
# 0.07714411293114853

print(rs.rand(3))
# [0.41864167 0.24060533 0.33237037]

print(rs.rand(2, 3))
# [[0.44510064 0.81320106 0.79076827]
#  [0.84813432 0.83270079 0.10677157]]

You can fix the seed.

rs_1 = np.random.RandomState(1234)
print(rs_1.rand())
# 0.1915194503788923

rs_2 = np.random.RandomState(1234)
print(rs_2.rand())
# 0.1915194503788923

Use functions

The methods of RandomState are also available as functions.

print(np.random.rand(2, 3))
# [[0.22135358 0.56604746 0.03200072]
#  [0.04187504 0.32511305 0.0366836 ]]

Use np.random.seed() to fix the seed.

np.random.seed(1234)
print(np.random.rand())
# 0.1915194503788923

np.random.seed(1234)
print(np.random.rand())
# 0.1915194503788923

Random numbers from a uniform distribution: np.random.rand, randint, etc.

Random floating-point numbers from 0.0 to 1.0 ([0.0, 1.0))

Random numbers uniformly distributed from 0.0 (inclusive) to 1.0 (exclusive), as denoted by [0.0, 1.0), can be generated using the Generator's random() method.

The first argument is size.

rng = np.random.default_rng()

print(rng.random())
# 0.11769302730981768

print(rng.random(3))
# [0.58905312 0.90484592 0.90395364]

print(rng.random((2, 3)))
# [[0.59463288 0.19670697 0.95594319]
#  [0.94165422 0.18974122 0.33570092]]

This method corresponds to np.random.random_sample() and np.random.rand(). In np.random.rand(), the shape is specified as consecutive positional arguments d0, d1, ..., dn.

print(np.random.random_sample((2, 3)))
# [[0.34446051 0.76218429 0.37339732]
#  [0.22533506 0.00148215 0.70198151]]

print(np.random.rand(2, 3))
# [[0.78823483 0.00620854 0.96619249]
#  [0.32573769 0.36434893 0.04472163]]

Random floating-point numbers in any range

Uniformly distributed random floating-point numbers in any range can be generated using the Generator's uniform() method.

Specify the first argument low, the second argument high, and the third argument size. low is inclusive and high is exclusive in the range [low, high).

rng = np.random.default_rng()

print(rng.uniform(-50.0, 50.0))
# 17.611381123655846

print(rng.uniform(-50.0, 50.0, 3))
# [ 5.80448109  6.64291183 22.27752257]

print(rng.uniform(-50.0, 50.0, (2, 3)))
# [[ 12.23855165  -9.97903127 -38.40667299]
#  [-14.42414448 -45.04563195  14.37486871]]

This method corresponds to np.random.uniform().

print(np.random.uniform(-50.0, 50.0, (2, 3)))
# [[-25.63149057  16.80691914  20.69418218]
#  [ 32.53480087 -10.83462837  15.18192629]]

Random integers in any range

Uniformly distributed random integers in any range can be generated using the Generator's integers() method.

Specify the first argument low, the second argument high, and the third argument size.

Omitting high sets the range to [0, low).

rng = np.random.default_rng()

print(rng.integers(100))
# 24

print(rng.integers(100, size=3))
# [ 9 25 27]

print(rng.integers(100, size=(2, 3)))
# [[78  2 42]
#  [25  6 16]]

Specifying high sets the range to [low, high).

print(rng.integers(100, 200, (2, 3)))
# [[134 142 129]
#  [154 180 103]]

Setting the argument endpoint to True includes the upper limit in the range ([0, low] or [low, high]).

print(rng.integers(100, 200, (2, 3), endpoint=True))
# [[170 157 172]
#  [121 200 191]]

This method corresponds to np.random.randint(). However, randint() does not have an endpoint argument, and the upper limit is always excluded from the range.

print(np.random.randint(100, 200, (2, 3)))
# [[120 121 138]
#  [159 140 197]]

Random numbers from a normal distribution: np.random.randn, normal, etc.

Standard normal distribution (mean=0, standard deviation=1)

Random numbers following a standard normal distribution (mean=0, standard deviation=1) can be generated using the Generator's standard_normal() method.

The first argument is size.

rng = np.random.default_rng()

print(rng.standard_normal())
# 0.08496250507973527

print(rng.standard_normal(3))
# [ 1.21769711  1.81125807 -0.87641522]

print(rng.standard_normal((2, 3)))
# [[-1.79057437  0.30921794  0.78466028]
#  [ 0.9669326  -0.23709503  0.17453728]]

This method corresponds to np.random.standard_normal() and np.random.randn(). In np.random.randn(), the shape is specified as consecutive positional arguments d0, d1, ..., dn.

print(np.random.standard_normal((2, 3)))
# [[ 1.59966341 -2.3255136  -0.90314338]
#  [-0.90576614  0.45550908 -0.88593054]]

print(np.random.randn(2, 3))
# [[ 0.13158995 -0.34018141  0.26866075]
#  [-0.35383739 -1.85442183 -0.1316313 ]]

Normal distribution (Gaussian distribution)

Random numbers following a normal distribution (Gaussian distribution) with specified mean and standard deviation can be generated using the Generator's normal() method.

Specify the first argument loc (mean), the second argument scale (standard deviation), and the third argument size.

rng = np.random.default_rng()

print(rng.normal(2, 2.5))
# 1.4099095964428612

print(rng.normal(2, 2.5, 3))
# [-1.02713245  2.80603029  6.84660003]

print(rng.normal(2, 2.5, (2, 3)))
# [[ 4.23662681  2.36596096 -0.08259898]
#  [ 2.27105608  1.58751381 -2.42582859]]

This method corresponds to np.random.normal().

print(np.random.normal(2, 2.5, (2, 3)))
# [[ 4.43180284  3.74464437  0.79083482]
#  [-0.3631814   0.39375677  7.8085918 ]]

Other distributions

In addition to uniform and normal distributions, various other distributions are also available for random number generation.

There are distributions like the binomial, beta, gamma, and Poisson distributions. Refer to the official documentation for the parameters that can be specified.

rng = np.random.default_rng()

print(rng.binomial(10, 0.5, (2, 3)))
# [[3 7 5]
#  [4 3 5]]

print(rng.beta(2, 2, (2, 3)))
# [[0.84643935 0.50674151 0.30812967]
#  [0.52728096 0.76007311 0.26255972]]

print(rng.gamma(5, 1, (2, 3)))
# [[5.6484851  8.28210475 2.65957385]
#  [2.00776839 6.65851101 7.77808412]]

print(rng.poisson(4, (2, 3)))
# [[1 6 3]
#  [5 2 1]]

Related Categories

Related Articles