📊 Array Attributes

NumPy arrays come packed with useful attributes that tell you everything you need to know about your data! Understanding these attributes is like having X-ray vision for your arrays - you can instantly see their structure, size, data type, and memory usage.

These attributes are essential for data analysis, debugging, and writing efficient code. Let's explore the most important ones!

import numpy as np

# Create a sample array to explore
data = np.array([[10, 20, 30, 40], 
                 [50, 60, 70, 80], 
                 [90, 100, 110, 120]])

print("Sample array:")
print(data)
print()

# Essential attributes at a glance
print("Quick array info:")
print(f"Shape: {data.shape}")      # Dimensions
print(f"Size: {data.size}")        # Total elements  
print(f"Data type: {data.dtype}")  # Type of elements
print(f"Dimensions: {data.ndim}")  # Number of dimensions
print(f"Memory usage: {data.nbytes} bytes")

📏 Shape - Understanding Dimensions

The shape attribute is one of the most important - it tells you the size of each dimension:

import numpy as np

# Different shaped arrays
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("1D array (vector):")
print(vector)
print(f"Shape: {vector.shape}")  # (5,)
print()

print("2D array (matrix):")
print(matrix)
print(f"Shape: {matrix.shape}")  # (2, 3) = 2 rows, 3 columns
print()

print("3D array (cube):")
print(cube)
print(f"Shape: {cube.shape}")    # (2, 2, 2) = 2 layers, 2 rows, 2 cols
print()

# Shape tells you total dimensions
print("Shapes explained:")
print(f"Vector {vector.shape}: {vector.shape[0]} elements")
print(f"Matrix {matrix.shape}: {matrix.shape[0]} rows × {matrix.shape[1]} columns")
print(f"Cube {cube.shape}: {cube.shape[0]} layers × {cube.shape[1]} rows × {cube.shape[2]} columns")

🔢 Size and Memory Attributes

Understanding how much data and memory your arrays use:

import numpy as np

# Create arrays with different sizes and types
small_array = np.array([1, 2, 3])
big_array = np.ones((100, 100))
float_array = np.array([1.1, 2.2, 3.3])

arrays = [
    ("Small array", small_array),
    ("Large array", big_array), 
    ("Float array", float_array)
]

print("Array size and memory comparison:")
print("=" * 50)

for name, arr in arrays:
    print(f"{name}:")
    print(f"  Shape: {arr.shape}")
    print(f"  Size: {arr.size:,} elements")
    print(f"  Memory: {arr.nbytes:,} bytes ({arr.nbytes/1024:.1f} KB)")
    print(f"  Per element: {arr.itemsize} bytes")
    print()

🎯 Data Types (dtype)

The dtype attribute tells you what kind of data your array contains:

import numpy as np

# Arrays with different data types
int_array = np.array([1, 2, 3])
float_array = np.array([1.0, 2.0, 3.0])
bool_array = np.array([True, False, True])
complex_array = np.array([1+2j, 3+4j])

print("Data type examples:")
print(f"Integers: {int_array} → dtype: {int_array.dtype}")
print(f"Floats: {float_array} → dtype: {float_array.dtype}")
print(f"Booleans: {bool_array} → dtype: {bool_array.dtype}")
print(f"Complex: {complex_array} → dtype: {complex_array.dtype}")
print()

# Explicitly specify data type
specific_int = np.array([1, 2, 3], dtype=np.int32)
specific_float = np.array([1, 2, 3], dtype=np.float32)

print("Explicitly specified types:")
print(f"int32: {specific_int} → dtype: {specific_int.dtype}")
print(f"float32: {specific_float} → dtype: {specific_float.dtype}")
print()

# Memory usage comparison
print("Memory usage by type:")
print(f"int64: {int_array.itemsize} bytes per element")
print(f"float64: {float_array.itemsize} bytes per element") 
print(f"bool: {bool_array.itemsize} bytes per element")

📐 Dimensional Attributes

Understanding array dimensionality:

import numpy as np

# Arrays with different dimensions
scalar = np.array(42)           # 0D
vector = np.array([1, 2, 3])    # 1D  
matrix = np.array([[1, 2], [3, 4]])  # 2D
tensor = np.array([[[1, 2]], [[3, 4]]])  # 3D

arrays = [
    ("Scalar (0D)", scalar),
    ("Vector (1D)", vector),
    ("Matrix (2D)", matrix),
    ("Tensor (3D)", tensor)
]

print("Dimensional analysis:")
print("=" * 40)

for name, arr in arrays:
    print(f"{name}:")
    print(f"  Value: {arr}")
    print(f"  Shape: {arr.shape}")
    print(f"  Dimensions (ndim): {arr.ndim}")
    print(f"  Size: {arr.size}")
    print()

🔧 Practical Attribute Usage

Real-world scenarios where attributes are essential:

import numpy as np

# Practical example: Working with image data
image_data = np.random.randint(0, 256, size=(100, 100, 3), dtype=np.uint8)

print("Image data analysis:")
print(f"Shape: {image_data.shape}")  # (height, width, channels)
print(f"Dimensions: {image_data.ndim}D array")
print(f"Data type: {image_data.dtype}")
print(f"Total pixels: {image_data.size:,}")
print(f"Memory usage: {image_data.nbytes:,} bytes ({image_data.nbytes/1024:.1f} KB)")
print()

# Extract image properties
height, width, channels = image_data.shape
print("Image properties:")
print(f"Height: {height} pixels")
print(f"Width: {width} pixels") 
print(f"Channels: {channels} (RGB)")
print(f"Pixel values range: {image_data.min()} to {image_data.max()}")

# Memory per pixel
print(f"Memory per pixel: {image_data.itemsize * channels} bytes")

📊 Array Information Methods

Beyond simple attributes, NumPy provides methods for detailed information:

import numpy as np

# Create a sample array
data = np.array([[1.5, 2.8, 3.2], 
                 [4.1, 5.9, 6.3]], dtype=np.float32)

print("Sample array:")
print(data)
print()

print("Detailed array information:")
print("=" * 30)

# Basic attributes
print(f"Shape: {data.shape}")
print(f"Size: {data.size}")
print(f"Data type: {data.dtype}")
print(f"Dimensions: {data.ndim}")
print(f"Item size: {data.itemsize} bytes")
print(f"Total memory: {data.nbytes} bytes")
print()

# Array flags (advanced properties)
print("Array flags:")
print(f"C-contiguous: {data.flags.c_contiguous}")
print(f"Fortran-contiguous: {data.flags.f_contiguous}")
print(f"Writeable: {data.flags.writeable}")
print(f"Aligned: {data.flags.aligned}")

🎮 Practice with Attributes

Let's practice inspecting different types of arrays:

import numpy as np

print("Array attribute practice:")
print("=" * 40)

# 1. Random numbers array
random_array = np.random.random(100)
print("1. Random array:")
print(f"   Shape: {random_array.shape}, Size: {random_array.size}")
print(f"   Type: {random_array.dtype}, Memory: {random_array.nbytes} bytes")
print()

# 2. Zero matrix
zero_matrix = np.zeros((3, 4))
print("2. Zero matrix:")
print(f"   Shape: {zero_matrix.shape}, Dimensions: {zero_matrix.ndim}")
print(f"   Type: {zero_matrix.dtype}, Total memory: {zero_matrix.nbytes} bytes")
print()

# 3. RGB image simulation
rgb_image = np.random.randint(0, 256, (10, 10, 3), dtype=np.uint8)
print("3. RGB image simulation:")
print(f"   Shape: {rgb_image.shape} (height × width × channels)")
print(f"   Type: {rgb_image.dtype}, Item size: {rgb_image.itemsize} byte")
print(f"   Total memory: {rgb_image.nbytes} bytes")
print()

# 4. Different data types
int8_array = np.array([1, 2, 3], dtype=np.int8)
float32_array = np.array([1.0, 2.0, 3.0], dtype=np.float32)
bool_array = np.array([True, False, True])

print("4. Different data types:")
print(f"   int8: itemsize={int8_array.itemsize}, memory={int8_array.nbytes}")
print(f"   float32: itemsize={float32_array.itemsize}, memory={float32_array.nbytes}")
print(f"   bool: itemsize={bool_array.itemsize}, memory={bool_array.nbytes}")

🎯 Key Takeaways

🎉 Section Complete!

Congratulations! You've completed the "Getting Started" section and now have a solid foundation in NumPy basics. You understand what NumPy is, how to install it, create arrays, compare them to lists, and inspect their attributes.

🚀 What's Next?

Ready to dive deeper into NumPy? The next section covers "Creating Arrays" where you'll learn advanced techniques for generating arrays efficiently.

Continue to: Creating Arrays

You're well on your way to NumPy mastery! 🔢⚡🎯

Was this helpful?

😔Poor
🙁Fair
😊Good
😄Great
🤩Excellent