0% found this document useful (0 votes)
11 views27 pages

Basic Array Creation and Operations

The document provides a comprehensive introduction to NumPy, a Python library for numerical computing, covering basic array creation, operations, indexing, slicing, and advanced features like fancy indexing. It includes examples of statistical operations, linear algebra, reshaping, broadcasting, and creating random arrays, demonstrating the efficiency of NumPy compared to standard Python lists. Additionally, it explains the structure of arrays, including scalars, vectors, matrices, and higher-dimensional arrays, along with their properties and performance benefits.

Uploaded by

vasantha
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
11 views27 pages

Basic Array Creation and Operations

The document provides a comprehensive introduction to NumPy, a Python library for numerical computing, covering basic array creation, operations, indexing, slicing, and advanced features like fancy indexing. It includes examples of statistical operations, linear algebra, reshaping, broadcasting, and creating random arrays, demonstrating the efficiency of NumPy compared to standard Python lists. Additionally, it explains the structure of arrays, including scalars, vectors, matrices, and higher-dimensional arrays, along with their properties and performance benefits.

Uploaded by

vasantha
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 27

1.

Basic Array Creation and Operations

```python

import numpy as np

# Creating an array from a list

array = np.array([1, 2, 3, 4, 5])

print("Array:", array)

# Creating an array of zeros and ones

zeros = np.zeros((2, 3)) # 2x3 matrix of zeros

ones = np.ones((2, 3)) # 2x3 matrix of ones

print("Zeros:\n", zeros)

print("Ones:\n", ones)

# Adding two arrays

array2 = np.array([5, 4, 3, 2, 1])

sum_array = array + array2

print("Sum of arrays:", sum_array)

2. Array Indexing and Slicing

```python

# Creating a 3x3 matrix

matrix = np.array([[1, 2, 3],

[4, 5, 6],

[7, 8, 9]])

# Accessing elements

print("Element at (0,0):", matrix[0, 0]) # 1


print("First row:", matrix[0]) # [1, 2, 3]

# Slicing a sub-matrix

sub_matrix = matrix[:2, 1:] # top-right 2x2 sub-matrix

print("Sub-matrix:\n", sub_matrix)

3.NumPy Fancy Indexing

In NumPy, fancy indexing allows us to use an array of indices to access multiple array elements at once.

Fancy indexing can perform more advanced and efficient array operations, including conditional filtering,
sorting, and so on.

import numpy as np

# create a numpy array


array1 = np.array([1, 2, 3, 4, 5, 6, 7, 8])

# select elements at index 1, 2, 5, 7


select_elements = array1[[1, 2, 5, 7]]

print(select_elements)

# Output: [2 3 6 8]

3. Element-wise Operations

```python
```

a = np.array([1, 2, 3])

b = np.array([4, 5, 6])

# Element-wise addition, multiplication

print("a + b:", a + b) # [5, 7, 9]

print("a * b:", a * b) # [4, 10, 18]

print("a squared:", a ** 2) # [1, 4, 9]

4. Statistical Operations

```python

data = np.array([10, 20, 30, 40, 50])

print("Mean:", np.mean(data)) # 30.0

print("Standard deviation:", np.std(data)) # 14.14

print("Sum:", np.sum(data)) # 150

print("Maximum:", np.max(data)) # 50

```

5. Linear Algebra (Matrix Multiplication)

```python

# Define two matrices

A = np.array([[1, 2], [3, 4]])

B = np.array([[5, 6], [7, 8]])

# Matrix multiplication

C = np.dot(A, B)

print("Matrix product:\n", C)

```

### 6. Reshaping and Broadcasting

```python

# Reshaping a 1D array to 2D

array_1d = np.array([1, 2, 3, 4, 5, 6])


array_2d = array_1d.reshape(2, 3)

print("2D array:\n", array_2d)

# Broadcasting example

array_3x1 = np.array([[1], [2], [3]])

array_1x3 = np.array([10, 20, 30])

# Broadcasting (3x1 and 1x3 become 3x3)

broadcasted_sum = array_3x1 + array_1x3

print("Broadcasted sum:\n", broadcasted_sum)

```

### 7. Creating Random Arrays

```python

# Random values between 0 and 1

random_array = np.random.rand(3, 3)

print("Random array:\n", random_array)

# Random integers

random_ints = np.random.randint(0, 10, size=(3, 3))

print("Random integers:\n", random_ints)

```

These examples should provide a solid start for using NumPy in data analysis, linear algebra, and other
numerical tasks! Let me know if you need more details on any of these examples.
Introduction to NumPy

 NumPy is a Python library that is mainly used to work with arrays. An array is a collection of items that
are stored next to each other in memory.
 For now, just think of them like Python lists.
 NumPy is written in Python and C.
 The calculations in NumPy are done by the parts that are written in C, which makes them extremely
fast compared to normal Python code.

Installation

 Make sure Python & Pip are installed in your computer.


 Then open command prompt or terminal and run pip install numpy

Creating Arrays

 We can create a NumPy array by using the numpy module's array() function.

import numpy as np

arr = np.array([3, 5, 7, 9])


print(type(arr))

Output:
<class 'numpy.ndarray'>

Table 4-2. NumPy data types

Type
Type Description
Code
int8, uint8 i1, u1 Signed and unsigned 8-bit (1 byte) integer types
int16, uint16 i2, u2 Signed and unsigned 16-bit integer types
int32, uint32 i4, u4 Signed and unsigned 32-bit integer types
int64, uint64 i8, u8 Signed and unsigned 32-bit integer types
float16 f2 Half-precision floating point
float32 f4 or f Standard single-precision floating point. Compatible with C float
Standard double-precision floating point. Compatible with C double and
float64 f8 or d
Python float object
float128 f16 or g Extended-precision floating point
complex64, complex128, c8, c16,
Complex numbers represented by two 32, 64, or 128 floats, respectively
complex256 c32
bool ? Boolean type storing True and False values
object O Python object type
Fixed-length string type (1 byte per character). For example, to create a
string_ S
string dtype with length 10, use 'S10'.
Fixed-length unicode type (number of bytes platform specific). Same
unicode_ U
specification semantics as string_ (e.g. 'U10').

 You can explicitly convert or cast an array from one dtype to another using ndarray’s astype method:
Dimensions or Axes

 In NumPy, dimensions are called axes (plural for axis).


 I like to think of an axis as a line along which items can be stored.
 A simple list or a 1 dimensional array can be visualized as:

We will now look at the following:

1. Scalars (0D Arrays)


2. Vectors (1D Arrays)
3. Matrices (2D Arrays)
4. 3D Arrays
5. 4D Arrays

1) Scalars (0D Arrays)

 A scalar is just a single value.

import numpy as np

s = np.array(21)
print("Number of axes:", s.ndim)
print("Shape:", s.shape)

Output:

Number of axes: 0
Shape: ()
Here we have used 2 properties of a numpy array:

 ndim: It returns the number of dimensions (or axes) in an array. It returns 0 here because a value in
itself does not have any dimensions.
 shape: It returns a tuple that contains the number of values along each axis of an array. Since a scalar
has 0 axes, it returns an empty tuple.

2) Vectors (1D Arrays)

 A vector is a collection of values.

import numpy as np

vec = np.array([-1, 2, 7, 9, 2])


print("Number of axes:", vec.ndim)
print("Shape:", vec.shape)

Output:

Number of axes: 1
Shape: (5,)

 vec.shape[0] gives us the number of values in our vector, which is 5 here.

3) Matrices (2D Arrays)

 A matrix is a collection of vectors.

import numpy as np

mat = np.array([
[1, 2, 3],
[5, 6, 7]
])

print("Number of axes:", mat.ndim)


print("Shape:", mat.shape)

Output:

Number of axes: 2
Shape: (2, 3)

 Here we created a 2x3 matrix (2D array) using a list of lists.


 Since a matrix has 2 axes, mat.shape tuple contains two values: the first value is the number of rows
and the second value is the number of columns.
 Each item (row) in a 2D array is a vector (1D array).

4) 3D Arrays

 A 3D array is a collection of matrices.

import numpy as np

t = np.array([
[[1, 3, 9],
[7, -6, 2]],

[[2, 3, 5],
[0, -2, -2]],

[[9, 6, 2],
[-7, -3, -12]],

[[2, 4, 5],
[-1, 9, 8]]
])
print("Number of axes:", t.ndim)
print("Shape:", t.shape)

Output:

Number of axes: 3
Shape: (4, 2, 3)
 Here we created a 3D array by using a list of 4 lists, which themselves contain 2 lists.
 Each item in a 3D array is a matrix (1D array). Note that the last matrix in the array is the front-most in
the image.

5) 4D Ararys

 After looking at the above examples, we see a pattern here.


 An n-dimensional array is a collection of n-1 dimensional arrays, for n > 0.
 I hope that now you have a better idea of visualizing multidimensional arrays.
Accessing Array Elements

 Just like Python lists, the indexes in NumPy arrays start with 0.

import numpy as np

vec = np.array([-3, 4, 6, 9, 8, 3])


print("vec - 4th value:", vec[3])

vec[3] = 19
print("vec - 4th value (changed):", vec[3])

mat = np.array([
[2, 4, 6, 8],
[10, 12, 14, 16]
])
print("mat - 1st row:", mat[0])
print("mat - 2nd row's 1st value:", mat[1, 0])
print("mat - last row's last value:", mat[-1, -1])

Output:

vec - 4th value: 9


vec - 4th value (changed): 19
mat - 1st row: [2 4 6 8]
mat - 2nd row's 1st value: 10
mat - last row's last value: 16

NumPy arrays also support slicing.

# continuing the above code

print("vec - 2nd to 4th:", vec[1:4])


print("mat - 1st rows 1st to 3rd values:", mat[0, 0:3])
print("mat - 2nd column:", mat[:, 1])

Output:

vec - 2nd to 4th: [4 6 9]


mat - 1st row's 1st to 3rd values: [2 4 6]
mat - 2nd column: [ 4 12]

 In the last example, [:, 1] tells "get 2nd value from all rows".
 Hence, we get the 2nd column of the matrix as the output.
Example: Indexing in a 4D Array

 Let's say we want to access the circled value.


 It is located in the 2nd 3D array's last matrix's 2nd row's 2nd column.
 It's a lot so take your time.
 Here's how to access it:
 arr[2, -1, 1, 1]

Python VS NumPy

 Calculations in NumPy are extremely fast compared to normal Python code.


 Let's see the difference.
 We will create two lists with 10 million numbers from 0 to 9,999,999, add them element-wise and
measure the time it takes.
 Then we will convert both lists to NumPy arrays and do the same.

import numpy as np
import time

l1 = list(range(10000000))
l2 = list(range(10000000))
sum = []

then = time.time()
for i in range(len(l1)):
sum.append(l1[i] + l2[i])

print(f"With just Python: {time.time() - then: .2f}s")

arr1 = np.array(l1)
arr2 = np.array(l2)

then = time.time()
sum = arr1 + arr2
print(f"With NumPy: {time.time() - then: .2f}s")

Output:
With just Python: 2.30s
With NumPy: 0.14s

 In this case, NumPy was 16x faster than raw Python.

Fancy indexing

 Fancy indexing in NumPy refers to accessing elements of an array using an array of indices (integer
arrays) rather than single integer values, slices, or boolean masks.
 It is a powerful and flexible way to extract or manipulate data.

1. Basics of Fancy Indexing

Fancy indexing works by passing an array (or list) of indices to select multiple elements.

Example:

```python

import numpy as np

arr = np.array([10, 20, 30, 40, 50])

# Fancy indexing with an array of indices

indices = [0, 2, 4]

result = arr[indices] # [10, 30, 50]

```

2. Fancy Indexing with 2D Arrays

Fancy indexing allows selecting specific rows, columns, or elements in 2D arrays.

Example: Selecting Rows

```python

arr = np.array([[10, 20, 30],

[40, 50, 60],

[70, 80, 90]])

# Select first and third rows

row_indices = [0, 2]

result = arr[row_indices]

# [[10, 20, 30],


# [70, 80, 90]]

```

Example: Selecting Specific Elements

```python

# Select (0,0), (1,1), and (2,2) elements

row_indices = [0, 1, 2]

col_indices = [0, 1, 2]

diagonal = arr[row_indices, col_indices] # [10, 50, 90]

```

3. Fancy Indexing with Mixed Slices and Index Arrays:

You can combine slicing with fancy indexing.

Example:

```python

# Select specific rows and all columns

result = arr[[0, 2], :]

# [[10, 20, 30],

# [70, 80, 90]]

```

4. Assigning Values Using Fancy Indexing

Fancy indexing can also be used to modify specific elements in the array.

Example:

```python

arr = np.array([10, 20, 30, 40, 50])

# Assign new values to specific indices

arr[[0, 2, 4]] = [100, 300, 500]

# [100, 20, 300, 40, 500]


```

5. Repeating and Rearranging Elements

Fancy indexing allows you to repeat or rearrange elements easily.

Example:

```python

arr = np.array([10, 20, 30, 40, 50])

# Rearrange elements

rearranged = arr[[4, 3, 2, 1, 0]] # [50, 40, 30, 20, 10]

# Repeat elements

repeated = arr[[0, 0, 1, 1]] # [10, 10, 20, 20]

```

6. Fancy Indexing with Boolean Masking

Fancy indexing can also be combined with boolean masks for more complex selections.

Example:

```python

arr = np.array([10, 20, 30, 40, 50])

# Boolean mask for selecting elements > 30

mask = arr > 30

selected = arr[mask] # [40, 50]

```

7. Fancy Indexing with Multidimensional Arrays

Fancy indexing also works on multidimensional arrays.

Example:

```python

arr = np.array([[10, 20, 30],

[40, 50, 60],

[70, 80, 90]])

# Select (0,1), (1,2), and (2,0)


row_indices = [0, 1, 2]

col_indices = [1, 2, 0]

selected = arr[row_indices, col_indices] # [20, 60, 70]

```

8. Tips and Pitfalls

 Fancy indexing does not follow the original shape of the array; it creates a new array based on the
shape of the index arrays.
 Fancy indexing generates a copy of the data, not a view.
 Modifications to the result won't affect the original array.
 Fancy indexing is an indispensable feature for flexible data selection and manipulation in NumPy
arrays.

Key Differences Between Basic Indexing & Fancy Indexing

S.no Feature Basic Indexing Fancy Indexing


1. Input Type Integer indices or slices Arrays or lists of indices
(`:`)
2. Output View of the original Copy of the data
array (if possible
3. Shape of Output Tries to maintain original Follows the shape of the
structure index array
4. Modification Affects the original array Does not affect the
(view) original array
5. Performance More efficient (view, no Less efficient (data
data copy) copy)
6. Use Cases Accessing contiguous Accessing arbitrary
data elements

Example to Highlight the Difference

Basic Indexing:

```python

arr = np.array([10, 20, 30, 40, 50])

# Basic indexing creates a view

view = arr[1:4] # [20, 30, 40]

view[0] = 100
print(arr) # [10, 100, 30, 40, 50]

```

Fancy Indexing:

```python

arr = np.array([10, 20, 30, 40, 50])

# Fancy indexing creates a copy

copy = arr[[1, 3, 4]] # [20, 40, 50]

copy[0] = 100

print(arr) # [10, 20, 30, 40, 50] (unchanged)

```
ARRAY FUNCTIONS

Array Operations Functions

Array Creation Functions np.array(), np.zeros(), np.ones(), np.empty(), etc.

Array Manipulation Functions np.reshape(), np.transpose(), etc.

Array Mathematical Functions np.add(), np.subtract(), np.sqrt(), np.power(), etc.

Array Statistical Functions np.median(), np.mean(), np.std(), and np.var().

Array Input and Output Functions np.save(), np.load(), np.loadtxt(), etc.

Array Creation Functions

Array Manipulation Functions

Array Mathematical Functions


Array Statistical Functions

Array Input and Output Functions


Data Processing Using Arrays

 Using NumPy arrays enables you to express many kinds of data processing tasks as concise array
expressions that might otherwise require writing loops.
 This practice of replacing explicit loops with array expressions is commonly referred to as
vectorization.
 In general, vectorized array operations will often be one or two (or more) orders of magnitude faster
than their pure Python equivalents, with the biggest impact in any kind of numerical computations.

,,,python

points = np.arange(-5, 5, 0.01)


xs, ys = np.meshgrid(points, points)
ys
import matplotlib.pyplot as plt
z = np.sqrt(xs ** 2 + ys ** 2)
z
In : plt.imshow(z, cmap=plt.cm.gray); plt.colorbar()
Out: <matplotlib.colorbar.Colorbar instance at 0x4e46d40>

In : plt.title("Image plot of $\sqrt{x^2 + y^2}$ for a grid of values")


Out: <matplotlib.text.Text at 0x4565790>

Here I used the matplotlib function imshow to create an image plot from a 2D array of function values.

Linear algebra (numpy.linalg)

 The NumPy linear algebra functions rely on BLAS (Basic Linear Algebra Subprograms) and LAPACK
(Linear Algebra Package) to provide efficient low level implementations of standard linear algebra
algorithms.
 Those libraries may be provided by NumPy itself using C versions of a subset of their reference
implementations but, when possible, highly optimized libraries that take advantage of specialized
processor functionality are preferred.
 The SciPy library also contains a linalg submodule, and there is overlap in the functionality provided
by the SciPy and NumPy submodules.
 SciPy contains functions not found in numpy.linalg, such as functions related to LU decomposition and
the Schur decomposition, multiple ways of calculating the pseudoinverse, and matrix transcendentals
such as the matrix logarithm.
 Some functions that exist in both have augmented functionality in scipy.linalg.
 For example, scipy.linalg.eig can take a second matrix argument for solving generalized eigenvalue
problems.
 Some functions in NumPy, however, have more flexible broadcasting options.
 For example, numpy.linalg.solve can handle “stacked” arrays, while scipy.linalg.solve accepts only a
single square array as its first argument.

Note

The term matrix as it is used on this page indicates a 2d numpy.array object, and not a numpy.matrix object.
The latter is no longer recommended, even for linear algebra.

The @ operator

Introduced in NumPy 1.10.0, the @ operator is preferable to other methods when computing the matrix
product between 2d arrays. The numpy.matmul function implements the @ operator.

Matrix and vector products

dot(a, b[, out]) Dot product of two arrays.


Compute the dot product of two or more arrays in a single
linalg.multi_dot(arrays, *[, out]) function call, while automatically selecting the fastest
evaluation order.
vdot(a, b, /) Return the dot product of two vectors.
vecdot(x1, x2, /[, out, casting, order, ...]) Vector dot product of two arrays.
linalg.vecdot(x1, x2, /, *[, axis]) Computes the vector dot product.
inner(a, b, /) Inner product of two arrays.
outer(a, b[, out]) Compute the outer product of two vectors.
matmul(x1, x2, /[, out, casting, order, ...]) Matrix product of two arrays.
linalg.matmul(x1, x2, /) Computes the matrix product.
tensordot(a, b[, axes]) Compute tensor dot product along specified axes.
linalg.tensordot(x1, x2, /, *[, axes]) Compute tensor dot product along specified axes.
einsum(subscripts, *operands[, out, dtype, ...]) Evaluates the Einstein summation convention on the operands.
Evaluates the lowest cost contraction order for an einsum
einsum_path(subscripts, *operands[, optimize])
expression by considering the creation of intermediate arrays.
linalg.matrix_power(a, n) Raise a square matrix to the (integer) power n.
kron(a, b) Kronecker product of two arrays.
linalg.cross(x1, x2, /, *[, axis]) Returns the cross product of 3-element vectors.

Decompositions

linalg.cholesky(a, /, *[, upper]) Cholesky decomposition.


linalg.outer(x1, x2, /) Compute the outer product of two vectors.
linalg.qr(a[, mode]) Compute the qr factorization of a matrix.
linalg.svd(a[, full_matrices, compute_uv, ...]) Singular Value Decomposition.
linalg.svdvals(x, /) Returns the singular values of a matrix (or a stack of matrices) x.

Matrix eigenvalues

linalg.eig(a) Compute the eigenvalues and right eigenvectors of a square array.


Return the eigenvalues and eigenvectors of a complex Hermitian (conjugate
linalg.eigh(a[, UPLO])
symmetric) or a real symmetric matrix.
linalg.eigvals(a) Compute the eigenvalues of a general matrix.
linalg.eigvalsh(a[, UPLO]) Compute the eigenvalues of a complex Hermitian or real symmetric matrix.

Norms and other numbers

linalg.norm(x[, ord, axis, keepdims]) Matrix or vector norm.


linalg.matrix_norm(x, /, *[, keepdims, ord]) Computes the matrix norm of a matrix (or a stack of matrices) x.
linalg.vector_norm(x, /, *[, axis, ...]) Computes the vector norm of a vector (or batch of vectors) x.
linalg.cond(x[, p]) Compute the condition number of a matrix.
linalg.det(a) Compute the determinant of an array.
linalg.matrix_rank(A[, tol, hermitian, rtol]) Return matrix rank of array using SVD method
Compute the sign and (natural) logarithm of the determinant of an
linalg.slogdet(a)
array.
trace(a[, offset, axis1, axis2, dtype, out]) Return the sum along diagonals of the array.
Returns the sum along the specified diagonals of a matrix (or a
linalg.trace(x, /, *[, offset, dtype])
stack of matrices) x.

Solving equations and inverting matrices

linalg.solve(a, b) Solve a linear matrix equation, or system of linear scalar equations.


linalg.tensorsolve(a, b[, axes]) Solve the tensor equation a x = b for x.
linalg.lstsq(a, b[, rcond]) Return the least-squares solution to a linear matrix equation.
linalg.inv(a) Compute the inverse of a matrix.
linalg.pinv(a[, rcond, hermitian, rtol]) Compute the (Moore-Penrose) pseudo-inverse of a matrix.
linalg.tensorinv(a[, ind]) Compute the 'inverse' of an N-dimensional array.

Other matrix operations

diagonal(a[, offset, axis1, axis2]) Return specified diagonals.


linalg.diagonal(x, /, *[, offset]) Returns specified diagonals of a matrix (or a stack of matrices) x.
linalg.matrix_transpose(x, /) Transposes a matrix (or a stack of matrices) x.

Exceptions

linalg.LinAlgError Generic Python-exception-derived object raised by linalg functions.

Commonly-used numpy.linalg functions

Functio
Description
n
Return the diagonal (or off-diagonal) elements of a square matrix as a 1D array, or convert a 1D array
diag
into a square matrix with zeros on the off-diagonal
dot Matrix multiplication
trace Compute the sum of the diagonal elements
Functio
Description
n
det Compute the matrix determinant
eig Compute the eigenvalues and eigenvectors of a square matrix
inv Compute the inverse of a square matrix
pinv Compute the Moore-Penrose pseudo-inverse inverse of a matrix
qr Compute the QR decomposition
svd Compute the singular value decomposition (SVD)
solve Solve the linear system Ax = b for x, where A is a square matrix
lstsq Compute the least-squares solution to Ax = b

RANDOM NUMBERS USING ARRAYS

 NumPy provides a robust set of functions for generating random numbers and performing random
sampling through its numpy.random module.
 These functions are versatile and allow for generating random numbers from various distributions,
controlling reproducibility, and sampling efficiently.

1. Basic Random Numbers

**Generate Uniformly Distributed Random Numbers**

```python

import numpy as np

# Single random number

random_number = np.random.rand() # Example: 0.5488135039273248

# Array of random numbers

random_array = np.random.rand(3, 4) # 3x4 array with values in [0, 1)

```

**Generate Random Integers**

- Generate random integers from a specified range.

```python

# Single random integer in range [low, high)

random_int = np.random.randint(1, 10) # Example: 7

# Array of random integers

random_integers = np.random.randint(1, 10, size=(3, 3))

# 3x3 array with integers between 1 and 9

```

2. Seeding the Random Number Generator


- Seeds ensure reproducibility of random numbers.

```python

np.random.seed(42)

# Generate random numbers

print(np.random.rand(3)) # Same numbers will be generated if the seed is the same

```

3. Random Sampling from Distributions

#Standard Normal Distribution (Mean = 0, Std Dev = 1)

```python

# Single random value

random_normal = np.random.randn() # Example: 0.4967141530112327

# Array of random values

random_normals = np.random.randn(3, 4) # 3x4 array from standard normal

```

## **Custom Normal Distribution**

- Specify mean and standard deviation.

```python

mean = 5

std_dev = 2

# Single random value

custom_normal = np.random.normal(mean, std_dev) # Example: 4.56

# Array of random values

custom_normals = np.random.normal(mean, std_dev, size=(3, 4))

```

### **Other Common Distributions**

#### **Uniform Distribution**

- Random values between a specified range.

```python

# Uniform values between 1 and 10


uniform_values = np.random.uniform(1, 10, size=(3, 4))

```

## **Binomial Distribution**

- Number of successes in trials.

```python

n, p = 10, 0.5 # Number of trials, probability of success

binom_samples = np.random.binomial(n, p, size=5) # Example: [5, 6, 4, 5, 3]

```

#### **Poisson Distribution**

- Random samples from Poisson with a given mean.

```python

lam = 3 # Expected number of events

poisson_samples = np.random.poisson(lam, size=5) # Example: [2, 3, 4, 3, 2]

```

4. Random Choices

### **Random Selection from an Array**

```python

array = np.array([10, 20, 30, 40, 50])

# Single random choice

single_choice = np.random.choice(array) # Example: 30

# Array of random choices

random_choices = np.random.choice(array, size=3) # Example: [40, 20, 10]

# Random choices with replacement

choices_with_replacement = np.random.choice(array, size=3, replace=True)

# Random choices without replacement

choices_no_replacement = np.random.choice(array, size=3, replace=False)

```

5. Shuffling Arrays

### **Shuffle in Place**


```python

array = np.array([1, 2, 3, 4, 5])

np.random.shuffle(array) # Shuffle the array in place

print(array) # Example: [4, 2, 5, 3, 1]

```

### **Generate a Shuffled Copy**

```python

shuffled_array = np.random.permutation(array) # Returns a shuffled copy

```

6. Multidimensional Random Sampling

```python

# Random 3x3 array with values in [0, 1)

rand_array = np.random.rand(3, 3)

# Random integers in a 2x4 array

rand_ints = np.random.randint(1, 100, size=(2, 4))

```

7. Generating Random Numbers with Constraints

Use **masking** or conditional logic to impose constraints:

```python

# Random numbers between 0 and 1

rand_nums = np.random.rand(10)

# Keep only values > 0.5

filtered = rand_nums[rand_nums > 0.5]

```

8. Advanced Random Distributions

NumPy provides access to many distributions via `numpy.random.Generator`. Here are some examples:

### **Using Generator for Custom Randomness**

```python

rng = np.random.default_rng()
# Normal distribution

normal = rng.normal(loc=0, scale=1, size=(3, 3))

# Uniform distribution

uniform = rng.uniform(low=0, high=1, size=(2, 5))

```

You might also like