📊 Array Size and Indexing
Understanding array size and indexing is essential for accessing and manipulating your data! Size tells you how many elements you have, while indexing lets you pinpoint specific values. These fundamentals are the building blocks for all data analysis and array operations.
Think of indexing like having coordinates to find any piece of data in your array!
import numpy as np
# Array size and indexing basics
data = np.array([[10, 20, 30], [40, 50, 60], [70, 80, 90]])
print(f"Array: \n{data}")
print(f"Total size: {data.size} elements")
print(f"Shape: {data.shape}")
# Basic indexing examples
print(f"First element: {data[0, 0]}")
print(f"Middle element: {data[1, 1]}")
print(f"Last element: {data[2, 2]}")
print(f"First row: {data[0]}")
print(f"Last column: {data[:, 2]}")
📏 Understanding Array Size
Array size tells you the total number of elements, which is crucial for loops, memory planning, and data processing:
import numpy as np
# Different ways to measure array size
vector = np.array([1, 2, 3, 4, 5])
matrix = np.array([[1, 2, 3], [4, 5, 6]])
cube = np.array([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
print(f"1D Array: {vector}")
print(f" Size: {vector.size}")
print(f" Shape: {vector.shape}")
print(f" Length: {len(vector)}")
print(f"2D Array: \n{matrix}")
print(f" Size: {matrix.size}")
print(f" Shape: {matrix.shape}")
print(f" Rows: {matrix.shape[0]}, Columns: {matrix.shape[1]}")
print(f"3D Array shape: {cube.shape}")
print(f" Size: {cube.size}")
print(f" Calculation: {cube.shape[0]} × {cube.shape[1]} × {cube.shape[2]} = {cube.size}")
Size vs Shape vs Length:
size
: Total number of elements (all dimensions)shape
: Dimensions of each axislen()
: Size of first dimension only
🎯 1D Array Indexing
Start with 1D arrays - the simplest indexing case:
import numpy as np
# 1D indexing examples
temperatures = np.array([20.5, 22.1, 19.8, 21.3, 23.0, 18.7])
print(f"Temperatures: {temperatures}")
print(f"Array size: {temperatures.size}")
# Positive indexing
print(f"First temp: {temperatures[0]}°C")
print(f"Third temp: {temperatures[2]}°C")
print(f"Last temp: {temperatures[5]}°C")
# Negative indexing (from the end)
print(f"Last temp: {temperatures[-1]}°C")
print(f"Second to last: {temperatures[-2]}°C")
print(f"Third from end: {temperatures[-3]}°C")
# Using size for dynamic indexing
last_index = temperatures.size - 1
print(f"Last index: {last_index}")
print(f"Last temp (dynamic): {temperatures[last_index]}°C")
📊 2D Array Indexing
2D arrays need two indices: [row, column]
:
import numpy as np
# 2D indexing examples
grades = np.array([
[85, 92, 78, 91], # Student 1
[79, 88, 95, 82], # Student 2
[91, 85, 89, 94], # Student 3
[88, 90, 87, 89] # Student 4
])
print(f"Grades array: \n{grades}")
print(f"Shape: {grades.shape} (students, subjects)")
# Individual element access
print(f"Student 1, Subject 1: {grades[0, 0]}")
print(f"Student 2, Subject 3: {grades[1, 2]}")
print(f"Student 4, Subject 4: {grades[3, 3]}")
# Row and column access
print(f"Student 1 all grades: {grades[0]}") # Entire row
print(f"Subject 1 all grades: {grades[:, 0]}") # Entire column
print(f"Last student grades: {grades[-1]}") # Last row
print(f"Last subject grades: {grades[:, -1]}") # Last column
🧮 Multi-dimensional Indexing
For 3D and higher dimensions, you need more indices:
import numpy as np
# 3D array indexing
# Shape: (classes, students, subjects)
school_data = np.array([
[[85, 90, 78], [92, 88, 85]], # Class 1: 2 students, 3 subjects
[[79, 85, 91], [88, 92, 87]], # Class 2: 2 students, 3 subjects
[[91, 89, 94], [85, 87, 90]] # Class 3: 2 students, 3 subjects
])
print(f"School data shape: {school_data.shape}")
print(f"Classes: {school_data.shape[0]}")
print(f"Students per class: {school_data.shape[1]}")
print(f"Subjects: {school_data.shape[2]}")
# 3D indexing examples
print(f"Class 1, Student 1, Subject 1: {school_data[0, 0, 0]}")
print(f"Class 2, Student 2, Subject 3: {school_data[1, 1, 2]}")
# Accessing slices
print(f"All Class 1 data: \n{school_data[0]}")
print(f"Student 1 from all classes: \n{school_data[:, 0, :]}")
print(f"Subject 1 from all: {school_data[:, :, 0].flatten()}")
🔍 Array Size in Practice
Understanding size helps with data processing and validation:
import numpy as np
# Practical size usage
print("📊 Practical Array Size Usage")
print("=" * 30)
# Example 1: Data validation
sensor_data = np.random.randn(24, 7) # 24 hours, 7 days
expected_readings = 24 * 7
print(f"Sensor data shape: {sensor_data.shape}")
print(f"Expected readings: {expected_readings}")
print(f"Actual readings: {sensor_data.size}")
print(f"Data complete: {sensor_data.size == expected_readings}")
# Example 2: Memory estimation
image_height, image_width = 1080, 1920
color_channels = 3
total_pixels = image_height * image_width * color_channels
print(f"\nImage analysis:")
print(f"Resolution: {image_height}×{image_width}")
print(f"Total pixels: {image_height * image_width:,}")
print(f"With RGB channels: {total_pixels:,}")
# Create and check
image_array = np.zeros((image_height, image_width, color_channels), dtype=np.uint8)
print(f"Array size: {image_array.size:,}")
print(f"Memory usage: {image_array.nbytes / 1024 / 1024:.1f} MB")
🎯 Safe Indexing Practices
Avoid common indexing errors with these practices:
import numpy as np
# Safe indexing examples
data = np.array([10, 20, 30, 40, 50])
print(f"Data: {data}")
print(f"Valid indices: 0 to {len(data) - 1}")
# Safe index checking
def safe_get(array, index):
if 0 <= index < len(array):
return array[index]
else:
return f"Index {index} out of bounds"
# Test safe indexing
print(f"Index 2: {safe_get(data, 2)}")
print(f"Index 10: {safe_get(data, 10)}") # Out of bounds
print(f"Index -1: {safe_get(data, -1)}") # This would be valid in NumPy
# Using negative indices safely
print(f"Last element: {data[-1]}")
print(f"Second to last: {data[-2]}")
# Dynamic indexing with size
middle_index = data.size // 2
print(f"Middle element (index {middle_index}): {data[middle_index]}")
📋 Index vs Position Understanding
Understanding the difference between position and index is crucial:
import numpy as np
# Position vs Index explanation
scores = np.array([85, 92, 78, 95, 89])
print(f"Scores: {scores}")
print(f"Array size: {scores.size}")
print(f"\nPosition vs Index:")
for i in range(scores.size):
position = i + 1 # Human-friendly position
value = scores[i] # Computer index
print(f"Position {position} (Index {i}): {value}")
# Finding elements
target_score = 95
index_of_target = np.where(scores == target_score)[0]
if len(index_of_target) > 0:
idx = index_of_target[0]
print(f"\nScore {target_score} found at:")
print(f" Index: {idx}")
print(f" Position: {idx + 1}")
else:
print(f"Score {target_score} not found")
🔄 Size and Indexing with Reshaping
Array size stays constant during reshaping, but indexing patterns change:
import numpy as np
# Size and indexing with reshaping
original = np.arange(12) # 12 elements: 0, 1, 2, ..., 11
reshaped = original.reshape(3, 4)
print(f"Original: {original}")
print(f" Size: {original.size}")
print(f" Element at index 5: {original[5]}")
print(f"Reshaped: \n{reshaped}")
print(f" Size: {reshaped.size} (unchanged)")
print(f" Element at [1, 1]: {reshaped[1, 1]}")
# Finding equivalent positions
flat_index = 5
row = flat_index // 4 # 4 columns
col = flat_index % 4
print(f"Flat index {flat_index} → Row {row}, Column {col}")
print(f"Values match: {original[flat_index]} == {reshaped[row, col]}")
# Using flat indexing
print(f"Using flat indexing: {reshaped.flat[5]}")
🎯 Key Takeaways
🚀 What's Next?
Perfect! You now understand array properties completely - shape, dimensions, data types, size, and indexing. Next, let's explore array operations where you'll put this knowledge to work with mathematical computations.
Continue to: Basic Mathematical Operations
Ready to compute with arrays! ⚡✨
Was this helpful?
Track Your Learning Progress
Sign in to bookmark tutorials and keep track of your learning journey.
Your progress is saved automatically as you read.