Basic Array Creation and Operations
Basic Array Creation and Operations
```python
import numpy as np
print("Array:", array)
print("Zeros:\n", zeros)
print("Ones:\n", ones)
```python
[4, 5, 6],
[7, 8, 9]])
# Accessing elements
# Slicing a sub-matrix
print("Sub-matrix:\n", sub_matrix)
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
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])
4. Statistical Operations
```python
print("Maximum:", np.max(data)) # 50
```
```python
# Matrix multiplication
C = np.dot(A, B)
print("Matrix product:\n", C)
```
```python
# Reshaping a 1D array to 2D
# Broadcasting example
```
```python
random_array = np.random.rand(3, 3)
# Random integers
```
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
Creating Arrays
We can create a NumPy array by using the numpy module's array() function.
import numpy as np
Output:
<class 'numpy.ndarray'>
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
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.
import numpy as np
Output:
Number of axes: 1
Shape: (5,)
import numpy as np
mat = np.array([
[1, 2, 3],
[5, 6, 7]
])
Output:
Number of axes: 2
Shape: (2, 3)
4) 3D Arrays
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
Just like Python lists, the indexes in NumPy arrays start with 0.
import numpy as np
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:
Output:
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
Python VS NumPy
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])
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
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.
Fancy indexing works by passing an array (or list) of indices to select multiple elements.
Example:
```python
import numpy as np
indices = [0, 2, 4]
```
```python
row_indices = [0, 2]
result = arr[row_indices]
```
```python
row_indices = [0, 1, 2]
col_indices = [0, 1, 2]
```
Example:
```python
```
Fancy indexing can also be used to modify specific elements in the array.
Example:
```python
Example:
```python
# Rearrange elements
# Repeat elements
```
Fancy indexing can also be combined with boolean masks for more complex selections.
Example:
```python
```
Example:
```python
col_indices = [1, 2, 0]
```
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.
Basic Indexing:
```python
view[0] = 100
print(arr) # [10, 100, 30, 40, 50]
```
Fancy Indexing:
```python
copy[0] = 100
```
ARRAY FUNCTIONS
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
Here I used the matplotlib function imshow to create an image plot from a 2D array of function values.
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.
Decompositions
Matrix eigenvalues
Exceptions
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
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.
```python
import numpy as np
```
```python
```
```python
np.random.seed(42)
```
```python
```
```python
mean = 5
std_dev = 2
```
```python
```
## **Binomial Distribution**
```python
```
```python
```
4. Random Choices
```python
```
5. Shuffling Arrays
```
```python
```
```python
rand_array = np.random.rand(3, 3)
```
```python
rand_nums = np.random.rand(10)
```
NumPy provides access to many distributions via `numpy.random.Generator`. Here are some examples:
```python
rng = np.random.default_rng()
# Normal distribution
# Uniform distribution
```