Introduction
Two-dimensional arrays (matrices) are fundamental data structures in Python โ used for grids, images, game boards, mathematical matrices, and tabular data. Python offers several ways to create and work with 2D arrays, from plain lists of lists to NumPy arrays.
Creating 2D Arrays with List Comprehension
The corra 2D list:
rows = 4
cols = 3
# Correct: list comprehension creates independent rows
table = [[0] * cols for _ in range(rows)]
print(table)
# => [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
The Common Pitfall: Shared References
Never use [[value] * cols] * rows โ all rows will be the same object:
# WRONG: all rows share the same list object
table = [[0] * cols] * rows
table[1][1] = 99
print(table)
# => [[0, 99, 0], [0, 99, 0], [0, 99, 0], [0, 99, 0]]
# Changing rnged ALL rows!
# CORRECT: each row is a separate list
table = [[0] * cols for _ in range(rows)]
table[1][1] = 99
print(table)
# => [[0, 0, 0], [0, 99, 0], [0, 0, 0], [0, 0, 0]]
Initialize with Different Values
# All zeros
zeros = [[0] * 5 for _ in range(3)]
# All None
grid = [[None] * 5 for _ in range(3)]
# Sequential values
matrix = [[i * cols + j for j in range(cols)] for i in range(rows)]
# => [[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11]]
# Identity matrix
n = 4
else 0 for j in range(n)] for i in range(n)]
# => [[1,0,0,0], [0,1,0,0], [0,0,1,0], [0,0,0,1]]
| Homogeneous | | Best for | Small grids, game boards | Math, images, ML |
Resources
- Python Docs: List Comprehensions
- NumPy Array Creation
- NumPy Indexing matrix = list(zip(*matrix))[::-1] # rotate remaining return result
m = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
print(spiral_order(m))
=> [1, 2, 3, 6, 9, 8, 7, 4, 5]
## List of Lists vs NumPy: When to Use Each
| Feature | List of Lists | NumPy Array |
|---|---|---|
| Creation | Simple, no imports | Requires NumPy |
| Performance | Slow for math | Fast (C-optimized) |
| Memory | Higher | Lower |
| Vectorized ops | No (need loops) | Yes |
| Slicing | Limited | Powerful |
| Data types | Mixedvalues (0-255)
image = np.random.randint(0, 256, size=(100, 100), dtype=np.uint8)
# Flip horizontally
flipped = image[:, ::-1]
# Crop
cropped = image[10:50, 20:60]
# Threshold (binary)
binary = (image > 128).astype(np.uint8) * 255
# Resize (simple nearest-neighbor)
small = image[::2, ::2] # every other pixel
Spiral Matrix
def spiral_order(matrix):
"""Return elements of matrix in spiral order."""
result = []
while matrix:
result += matrix.pop(0) # top row
)
```python
# Initialize empty board
board = [['.' for _ in range(3)] for _ in range(3)]
def print_board(board):
for row in board:
print(' '.join(row))
print()
def make_move(board, row, col, player):
if board[row][col] == '.':
board[row][col] = player
return True
return False
make_move(board, 1, 1, 'X')
make_move(board, 0, 0, 'O')
print_board(board)
# O . .
# . X .
# . . .
Image as 2D Array
import numpy as np
# Grayscale image: 2D array of pixel # => 3 (flat index of max)
Reshaping
flat = np.arange(12) # [0, 1, 2, ..., 11]
# Reshape to 3x4
m = flat.reshape(3, 4)
print(m)
# [[ 0 1 2 3]
# [ 4 5 6 7]
# [ 8 9 10 11]]
# -1 means "infer this dimension"
m2 = flat.reshape(-1, 3) # shape: (4, 3)
m3 = flat.reshape(2, -1) # shape: (2, 6)
# Flatten back
print(m.flatten()) # => [ 0 1 2 3 4 5 6 7 8 9 10 11]
print(m.ravel()) # same but may return a view
Practical Examples
Game Board (Tic-Tac-Toe 6], [7, 8]])
Element-wise operations
print(a + b) # => [[ 6 8], [10 12]] print(a * b) # => [[ 5 12], [21 32]] print(a ** 2) # => [[ 1 4], [ 9 16]]
Matrix multiplication
print(a @ b) # => [[19 22], [43 50]] print(np.dot(a, b)) # same
Transpose
print(a.T) # => [[1 3], [2 4]]
Statistics
print(a.sum()) # => 10 print(a.sum(axis=0)) # => [4 6] (column sums) print(a.sum(axis=1)) # => [3 7] (row sums) print(a.mean()) # => 2.5 print(a.max()) # => 4 print(a.argmax())thon m = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
Single element
print(m[1, 2]) # => 6 (row 1, col 2)
Row slice
print(m[1, :]) # => [4 5 6] (entire row 1) print(m[0:2, :]) # => [[1 2 3], [4 5 6]] (rows 0-1)
Column slice
print(m[:, 1]) # => [2 5 8] (entire column 1) print(m[:, 1:3]) # => [[2 3], [5 6], [8 9]] (columns 1-2)
Boolean indexing
print(m[m > 5]) # => [6 7 8 9]
### NumPy Operations
```python
a = np.array([[1, 2], [3, 4]])
b = np.array([[5,```python
import numpy as np
# Create arrays
zeros = np.zeros((4, 3)) # 4x3 array of 0.0
ones = np.ones((3, 3)) # 3x3 array of 1.0
full = np.full((2, 4), 7) # 2x4 array of 7
eye = np.eye(4) # 4x4 identity matrix
random = np.random.rand(3, 3) # 3x3 random floats [0,1)
arange = np.arange(12).reshape(3, 4) # [[0,1,2,3],[4,5,6,7],[8,9,10,11]]
print(zeros)
# [[0. 0. 0.]
# [0. 0. 0.]
# [0. 0. 0.]
# [0. 0. 0.]]
NumPy Indexing and Slicing
# Using itertools
import itertools
flat = list(itertools.chain.from_iterable(matrix))
Rotate 90 Degrees
def rotate_90_clockwise(matrix):
return [list(row) for row in zip(*matrix[::-1])]
m = [[1, 2, 3],
[4, 5, 6],
[7, 8, 9]]
print(rotate_90_clockwise(m))
# => [[7, 4, 1], [8, 5, 2], [9, 6, 3]]
NumPy 2D Arrays (Recommended for Numerical Work)
NumPy arrays are faster, more memory-efficient, and support vectorized operations:
99 2 3 4 5 6 7 8 9
Iterate with indices
for i, row in enumerate(matrix): for j, val in enumerate(row): print(f"[{i}][{j}]={val}", end=" “)
## Common 2D Array Operations
### Transpose
```python
matrix = [[1, 2, 3],
[4, 5, 6]]
# Using zip
transposed = [list(row) for row in zip(*matrix)]
print(transposed)
# => [[1, 4], [2, 5], [3, 6]]
Flatten
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
# Using list comprehension
flat = [val for row in matrix for val in row]
printg Elements
```python
matrix = [[1, 2, 3],
[4, 5, 6],
[7, 8, 9]]
# Access element at row 1, col 2
print(matrix[1][2]) # => 6
# Modify element
matrix[0][0] = 99
print(matrix[0]) # => [99, 2, 3]
# Get a full row
print(matrix[1]) # => [4, 5, 6]
# Get a full column (no direct syntax โ use list comprehension)
col = [matrix[row][1] for row in range(len(matrix))]
print(col) # => [2, 5, 8]
# Iterate over all elements
for row in matrix:
for val in row:
print(val, end=" ")
# =
## Accessing and Modifyin
Comments