Numpy Arrays

Numpy Arrays#

Using Numpy will make our lives with arrays nicer than lists - Simplifies calcualtions - limits loops - allows for more complex calcuations with minimal work

# A 1-dimensional array (vector)
import numpy as np

array_1d = np.array([1, 2, 3, 4, 5])
print("1D Array:")
print(array_1d)
print(f"Shape: {array_1d.shape}")
print(f"Type: {array_1d.dtype}")

# A 2-dimensional array (matrix)
array_2d = np.array([[10, 20, 30], [40, 50, 60]])
print("\n2D Array:")
print(array_2d)
print(f"Shape: {array_2d.shape}")

# Array filled with zeros
zeros_array = np.zeros((2, 3))
print("\nArray of Zeros:")
print(zeros_array)

# Array filled with a range of numbers (like Python's range, but returns an array)
range_array = np.arange(0, 10, 2) # start, stop (exclusive), step
print("\nArray from a Range:")
print(range_array)
1D Array:
[1 2 3 4 5]
Shape: (5,)
Type: int64

2D Array:
[[10 20 30]
 [40 50 60]]
Shape: (2, 3)

Array of Zeros:
[[0. 0. 0.]
 [0. 0. 0.]]

Array from a Range:
[0 2 4 6 8]

Why bother with NP arrays? Lists are more work

import numpy as np

# -Python List Way
list_a = [1, 2, 3, 4]

doubled_list = list_a *2 
print(f"Improperly Doubled list: {doubled_list}") # will print "[1, 2, 3, 4, 1, 2, 3, 4]"

# We need to explicitly iterate over the list to properly double
doubled_list_loop = []
for x in list_a:
    doubled_list_loop.append(x*2)
print(f"Python List Doubled with Loop: {doubled_list_loop}")


doubled_list_1Line = [x * 2 for x in list_a]
print(f"Python List Doubled properly: {doubled_list_1Line}")

# NumPy Array Way
array_a = np.array([1, 2, 3, 4])
# NumPy performs the operation element-wise automatically
doubled_array = array_a * 2
print(f"NumPy Array Double: {doubled_array}")
# 3 lines, more readable
#note the formatting difference between the lists and the np arrays
#Lists have commas, arrays do not.
Improperly Doubled list: [1, 2, 3, 4, 1, 2, 3, 4]
Python List Doubled with Loop: [2, 4, 6, 8]
Python List Doubled properly: [2, 4, 6, 8]
NumPy Array Double: [2 4 6 8]
#don't need to import math with np arrays

import math # Need to import math for lists

# Python List Way
list_d = [4, 9, 16]

# Requires importing 'math' and using a comprehension
sqrt_list = [math.sqrt(x) for x in list_d]

print(f"List Square Roots: {sqrt_list}")

#NumPy Array Way
array_d = np.array([4, 9, 16])

# NumPy
sqrt_array = np.sqrt(array_d)

print(f"NumPy Square Roots: {sqrt_array}")
List Square Roots: [2.0, 3.0, 4.0]
NumPy Square Roots: [2. 3. 4.]
#Array Operations

import numpy as np

a = np.array([1, 2, 3, 4])
b = np.array([10, 20, 30, 40])

# Addition (element-wise)
c = a + b
print(f"a + b: {c}")

# Multiplication (element-wise)
d = a * 2
print(f"a * 2: {d}")

# Trigonometric functions (applied to every element)
e = np.sin(a)
print(f"sin(a): {e}")

# Comparison (returns a boolean array)
f = a > 2
print(f"a > 2: {f}")
a + b: [11 22 33 44]
a * 2: [2 4 6 8]
sin(a): [ 0.84147098  0.90929743  0.14112001 -0.7568025 ]
a > 2: [False False  True  True]
#Indexing Np Arrays and Slicing

import numpy as np

# Create a 3x3 matrix
matrix = np.array([[10, 11, 12],
                   [20, 21, 22],
                   [30, 31, 32]])
print("Original Matrix:")
print(matrix)

# Access a single element (Row 1, Column 2)
element = matrix[1, 2]
print(f"\nElement at [1, 2]: {element}\n") # Output: 22

# retrieve the last value in the array (bottom right)
slice_last = matrix[-1, -1]
print("Last value:")
print(f"{slice_last}\n")

# Slice the first two rows and all columns
slice_rows = matrix[:2, :]
print(f"First two rows:")
print(f"{slice_rows}\n")

# Slice the last row and all columns
slice_rows = matrix[-1, :]
print(f"Last row:")
print(f"{slice_rows}\n")

# Slice all rows, but only the second column
slice_column = matrix[:, 1]
print("Second column:")
print(f"{slice_column}\n")

# Slice all rows, but only the last column
slice_column = matrix[:, -1]
print("Last column:")
print(f"{slice_column}\n")
Original Matrix:
[[10 11 12]
 [20 21 22]
 [30 31 32]]

Element at [1, 2]: 22

Last value:
32

First two rows:
[[10 11 12]
 [20 21 22]]

Last row:
[30 31 32]

Second column:
[11 21 31]

Last column:
[12 22 32]
# More Slicing
import numpy as np

list = [ [127, 126, 80, 60],
  	  [120, 110, 65, 50],
  	  [100, 80, 50, 30] ]

print(f"list[1]: {list[1]}")
print(f"list[1][2]: {list[1][2]}\n")
#Will throw an error
#print(list[0:2,0:2])

#Np arrays allow for more dynamic slicing
A = np.array([ [127, 126, 80, 60],
  	  [120, 110, 65, 50],
  	  [100, 80, 50, 30] ])

print(f"A[1]: {A[1]}")
print(f"A[1][2]: {A[1][2]}\n")
print(f"A[0:2,0:2]:\n {A[0:2,0:2]}")
list[1]: [120, 110, 65, 50]
list[1][2]: 65

A[1]: [120 110  65  50]
A[1][2]: 65

A[0:2,0:2]:
 [[127 126]
 [120 110]]
#Stats

import numpy as np

data = np.array([[1, 5, 3],
                 [7, 2, 9]])
print("Data Array:")
print(f"{data}\n")

# Calculate the mean of all elements
total_mean = np.mean(data)
print(f"Overall Mean: {total_mean}\n")

# Calculate the sum of all elements
total_sum = np.sum(data)
print(f"Overall Sum: {total_sum}\n")

# Calculate the minimum value along an axis (axis=0 means columns)
min_col = np.min(data, axis=0)
print(f"Minimum per Column (axis=0): {min_col}\n") # Output: [1, 2, 3]

# Calculate the standard deviation along an axis (axis=1 means rows)
std_row = np.std(data, axis=1)
print(f"Standard Deviation per Row (axis=1): {std_row}\n")
Data Array:
[[1 5 3]
 [7 2 9]]

Overall Mean: 4.5

Overall Sum: 27

Minimum per Column (axis=0): [1 2 3]

Standard Deviation per Row (axis=1): [1.63299316 2.94392029]