What’s new or different — NumPy v2.4.dev0 Manual (original) (raw)
NumPy 1.17.0 introduced Generator as an improved replacement for the legacy RandomState. Here is a quick comparison of the two implementations.
- The normal, exponential and gamma generators use 256-step Ziggurat methods which are 2-10 times faster than NumPy’s default implementation instandard_normal, standard_exponential orstandard_gamma. Because of the change in algorithms, it is not possible to reproduce the exact random values using Generator for these distributions or any distribution method that relies on them.
In [1]: import numpy.random
In [2]: rng = np.random.default_rng()
In [3]: %timeit -n 1 rng.standard_normal(100000) ...: %timeit -n 1 numpy.random.standard_normal(100000) ...: 1.19 ms +- 22.6 us per loop (mean +- std. dev. of 7 runs, 1 loop each) 2.55 ms +- 16.7 us per loop (mean +- std. dev. of 7 runs, 1 loop each)
In [4]: %timeit -n 1 rng.standard_exponential(100000) ...: %timeit -n 1 numpy.random.standard_exponential(100000) ...: 634 us +- 41.5 us per loop (mean +- std. dev. of 7 runs, 1 loop each) 1.85 ms +- 27.9 us per loop (mean +- std. dev. of 7 runs, 1 loop each)
In [5]: %timeit -n 1 rng.standard_gamma(3.0, 100000) ...: %timeit -n 1 numpy.random.standard_gamma(3.0, 100000) ...: 2.42 ms +- 65.3 us per loop (mean +- std. dev. of 7 runs, 1 loop each) 5.01 ms +- 50.9 us per loop (mean +- std. dev. of 7 runs, 1 loop each)
- integers is now the canonical way to generate integer random numbers from a discrete uniform distribution. This replaces bothrandint and the deprecated random_integers.
- The rand and randn methods are only available through the legacyRandomState.
- Generator.random is now the canonical way to generate floating-point random numbers, which replaces RandomState.random_sample,sample, and ranf, all of which were aliases. This is consistent with Python’s random.random.
- All bit generators can produce doubles, uint64s and uint32s via CTypes (ctypes) and CFFI (cffi). This allows these bit generators to be used in numba.
- The bit generators can be used in downstream projects via Cython.
- All bit generators use SeedSequence to convert seed integers to initialized states.
- Optional
dtype
argument that acceptsnp.float32
ornp.float64
to produce either single or double precision uniform random variables for select distributions. integers accepts adtype
argument with any signed or unsigned integer dtype.- Uniforms (random and integers)
- Normals (standard_normal)
- Standard Gammas (standard_gamma)
- Standard Exponentials (standard_exponential)
In [6]: rng = np.random.default_rng()
In [7]: rng.random(3, dtype=np.float64) Out[7]: array([0.55783877, 0.18117425, 0.01543636])
In [8]: rng.random(3, dtype=np.float32) Out[8]: array([0.25276136, 0.17063433, 0.76469946], dtype=float32)
In [9]: rng.integers(0, 256, size=3, dtype=np.uint8) Out[9]: array([244, 29, 52], dtype=uint8)
- Optional
out
argument that allows existing arrays to be filled for select distributions- Uniforms (random)
- Normals (standard_normal)
- Standard Gammas (standard_gamma)
- Standard Exponentials (standard_exponential)
This allows multithreading to fill large arrays in chunks using suitable BitGenerators in parallel.
In [10]: rng = np.random.default_rng()
In [11]: existing = np.zeros(4)
In [12]: rng.random(out=existing[:2]) Out[12]: array([0.60900112, 0.4820143 ])
In [13]: print(existing) [0.60900112 0.4820143 0. 0. ]
- Optional
axis
argument for methods like choice,permutation and shuffle that controls which axis an operation is performed over for multi-dimensional arrays.
In [14]: rng = np.random.default_rng()
In [15]: a = np.arange(12).reshape((3, 4))
In [16]: a Out[16]: array([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11]])
In [17]: rng.choice(a, axis=1, size=5) Out[17]: array([[ 2, 0, 0, 0, 0], [ 6, 4, 4, 4, 4], [10, 8, 8, 8, 8]])
In [18]: rng.shuffle(a, axis=1) # Shuffle in-place
In [19]: a Out[19]: array([[ 1, 2, 3, 0], [ 5, 6, 7, 4], [ 9, 10, 11, 8]])
- Added a method to sample from the complex normal distribution (complex_normal)