For AI agents: use /llms.txt for the Nakafa content index.
Every element stored in a NumPy array has a specific type that determines how NumPy represents and processes it. Think of data types as storage formats designed for different kinds of information. A NumPy boolean occupies one byte, while a complex number stores separate real and imaginary components.
NumPy's type system ensures all array elements share the same data type so processing can stay efficient. This uniformity helps the underlying C code process data quickly. For details about each data type, check the NumPy data types documentation, which covers technical specifications and memory considerations.
NumPy accepts Python's built-in scalar types and also provides fixed-width scalar types when the exact representation matters:
bool or np.bool_) for True and False, stored as one byte per elementnp.int8 through np.int64) for signed whole numbers with explicit widthsnp.float16, np.float32, or np.float64) for floating-point values at different precisionsnp.complex64 or np.complex128) for values with real and imaginary componentsimport numpy as np
# Basic data type examples
bool_array = np.array([True, False, True], dtype=np.bool_)
print("Boolean array:", bool_array) # Output: Boolean array: [ True False True]
print("Dtype:", bool_array.dtype) # Output: Dtype: bool
int_array = np.array([1, 2, 3], dtype=np.int64)
print("Integer array:", int_array) # Output: Integer array: [1 2 3]
print("Dtype:", int_array.dtype) # Output: Dtype: int64
float_array = np.array([1.0, 2.5, 3.7], dtype=np.float64)
print("Float array:", float_array) # Output: Float array: [1. 2.5 3.7]
print("Dtype:", float_array.dtype) # Output: Dtype: float64NumPy provides detailed precision control with various sizes of numeric data types:
| Category | Data Type | Description | Value Range |
|---|---|---|---|
| Signed Integer | int8 | -bit signed integer | |
int16 | -bit signed integer | ||
int32 | -bit signed integer | ||
int64 | -bit signed integer | Very large range | |
| Unsigned Integer | uint8 | -bit unsigned integer | |
uint16 | -bit unsigned integer | ||
uint32 | -bit unsigned integer | ||
uint64 | -bit unsigned integer | Very large positive range | |
| Float | float16 | Half-precision float | , |
float32 | Single-precision float | , | |
float64 | Double-precision float | , | |
| Complex | complex64 | Complex number | Two -bit floats |
complex128 | Complex number | Two -bit floats |
You can specify a data type when creating an array or convert the values into a new array with another dtype:
import numpy as np
# Specify data type during array creation
a = np.array([0, 1, 2], dtype=float)
print("Array with float dtype:", a) # Output: Array with float dtype: [0. 1. 2.]
print("Dtype:", a.dtype) # Output: Dtype: float64
# Default is float for ones function
a = np.ones((3, 3))
print("Default ones dtype:", a.dtype) # Output: Default ones dtype: float64
# Change to integer
a = np.ones((3, 3), dtype=np.int64)
print("Ones with int dtype:", a.dtype) # Output: Ones with int dtype: int64
print("Array:")
print(a)
# Output:
# [[1 1 1]
# [1 1 1]
# [1 1 1]]NumPy automatically detects data types based on provided elements:
import numpy as np
# All integers
a = np.array([0, 1, 2])
print("All int - dtype:", a.dtype) # Typical 64-bit output: All int - dtype: int64
# All floats
a = np.array([0., 1., 2.])
print("All float - dtype:", a.dtype) # Output: All float - dtype: float64
# Mixed int and float
a = np.array([0, 1, 2.])
print("Mixed - dtype:", a.dtype) # Output: Mixed - dtype: float64
print("Array result:", a) # Output: Array result: [0. 1. 2.]Every NumPy array exposes attributes that describe its shape, element count, data type, and memory use.
The following example reads the core structural attributes from one two-dimensional array.
import numpy as np
# Create 2D array as example
a = np.array([[0, 1, 2], [3, 4, 5]], dtype=np.int64)
print("Array:")
print(a)
# Output:
# [[0 1 2]
# [3 4 5]]
print("Shape:", a.shape) # Output: Shape: (2, 3)
print("Ndim (dimensions):", a.ndim) # Output: Ndim (dimensions): 2
print("Size (total elements):", a.size) # Output: Size (total elements): 6
print("Dtype (data type):", a.dtype) # Output: Dtype (data type): int64
print("Bytes used by elements:", a.nbytes) # Output: Bytes used by elements: 48| Attribute | Function | Example Result |
|---|---|---|
ndarray.shape | Number of elements in each axis | (2, 3) for array |
ndarray.ndim | Number of axes/dimensions | 2 for two-dimensional array |
ndarray.size | Total number of elements | 6 for array |
ndarray.dtype | Element data type | int64, float64, etc |
ndarray.nbytes | Bytes used by the array elements | 48 for six int64 values |
All elements in a regular NumPy array share one data type. The numpy.dtype object explains how those values are stored and interpreted in memory. When inputs have different types, NumPy applies its promotion rules to find a compatible common dtype. That result depends on precision and type category, not on which input type appears most often.
import numpy as np
# All integers
a = np.array([0, 1, 2])
print("All int - dtype:", a.dtype) # Typical 64-bit output: All int - dtype: int64
# All floats
a = np.array([0., 1., 2.])
print("All float - dtype:", a.dtype) # Output: All float - dtype: float64
# Mixed integer and float (automatically becomes float)
a = np.array([0, 1, 2.])
print("Mixed - dtype:", a.dtype) # Output: Mixed - dtype: float64
print("Mixed result:", a) # Output: Mixed result: [0. 1. 2.]NumPy provides various ways to convert and manipulate array data types according to data analysis needs.
Data type conversion lets you choose another representation for later analysis. The astype() method returns a converted array; it does not change the original array in place. Converting floating-point values to integers truncates the fractional part toward zero rather than rounding it.
import numpy as np
# Original float array
original = np.array([1.1, 2.7, 3.9])
print("Original array:", original) # Output: Original array: [1.1 2.7 3.9]
print("Original dtype:", original.dtype) # Output: Original dtype: float64
# Convert to integer using astype
converted = original.astype(np.int64)
print("Converted to int:", converted) # Output: Converted to int: [1 2 3]
print("Converted dtype:", converted.dtype) # Output: Converted dtype: int64
# Convert to specific data type
float32_array = original.astype(np.float32)
print("Float32 dtype:", float32_array.dtype) # Output: Float32 dtype: float32
# Convert string to integer
string_array = np.array(['1', '2', '3'])
int_from_string = string_array.astype(np.int64)
print("From string:", int_from_string) # Output: From string: [1 2 3]
print("String to int dtype:", int_from_string.dtype) # Output: String to int dtype: int64Choosing the narrowest data type that still covers the required values and precision can reduce memory use substantially. Before narrowing a dtype, check its range so values do not overflow or lose needed precision.
import numpy as np
# Array with an explicit 64-bit integer data type
large_array_int64 = np.arange(1000000, dtype=np.int64)
print("Int64 itemsize:", large_array_int64.itemsize, "bytes") # Output: Int64 itemsize: 8 bytes
print("Int64 total memory:", large_array_int64.nbytes, "bytes") # Output: Int64 total memory: 8000000 bytes
# Array with smaller data type (int32)
large_array_int32 = np.arange(1000000, dtype=np.int32)
print("Int32 itemsize:", large_array_int32.itemsize, "bytes") # Output: Int32 itemsize: 4 bytes
print("Int32 total memory:", large_array_int32.nbytes, "bytes") # Output: Int32 total memory: 4000000 bytes
# Memory savings
memory_saved = large_array_int64.nbytes - large_array_int32.nbytes
print("Memory saved:", memory_saved, "bytes") # Output: Memory saved: 4000000 bytes
print("Memory saved percentage:", (memory_saved / large_array_int64.nbytes) * 100, "%") # Output: Memory saved percentage: 50.0 %The itemsize attribute makes the precision and memory trade-off visible for each array.
import numpy as np
# Create arrays with various data types
arrays = {
'int8': np.array([1, 2, 3], dtype=np.int8),
'int32': np.array([1, 2, 3], dtype=np.int32),
'int64': np.array([1, 2, 3], dtype=np.int64),
'float32': np.array([1.0, 2.0, 3.0], dtype=np.float32),
'float64': np.array([1.0, 2.0, 3.0], dtype=np.float64)
}
print("Data Type Information:")
print("=" * 50)
for name, arr in arrays.items():
print(f"{name:8} - itemsize: {arr.itemsize:2} bytes, dtype: {arr.dtype}")
# Output:
# Data Type Information:
# ==================================================
# int8 - itemsize: 1 bytes, dtype: int8
# int32 - itemsize: 4 bytes, dtype: int32
# int64 - itemsize: 8 bytes, dtype: int64
# float32 - itemsize: 4 bytes, dtype: float32
# float64 - itemsize: 8 bytes, dtype: float64Understanding array attributes is crucial for debugging, optimization, and effective data manipulation in scientific programming.
Analysis functions help you read array characteristics quickly. This is useful when working with complex data or debugging programs.
import numpy as np
def analyze_array(arr, name="Array"):
"""Function to analyze array structure"""
print(f"\n=== Analysis {name} ===")
print(f"Shape: {arr.shape}")
print(f"Dimensions: {arr.ndim}")
print(f"Size: {arr.size}")
print(f"Data type: {arr.dtype}")
print(f"Item size: {arr.itemsize} bytes")
print(f"Total memory: {arr.nbytes} bytes")
if arr.ndim <= 2:
print(f"Array content:\n{arr}")
# Example analysis of various arrays
array_1d = np.array([1, 2, 3, 4, 5], dtype=np.int64)
array_2d = np.array([[1, 2, 3], [4, 5, 6]], dtype=np.int64)
array_3d = np.array([[[1, 2], [3, 4]], [[5, 6], [7, 8]]], dtype=np.int64)
analyze_array(array_1d, "1D")
analyze_array(array_2d, "2D")
analyze_array(array_3d, "3D")
# Output:
# === Analysis 1D ===
# Shape: (5,)
# Dimensions: 1
# Size: 5
# Data type: int64
# Item size: 8 bytes
# Total memory: 40 bytes
# Array content:
# [1 2 3 4 5]
#
# === Analysis 2D ===
# Shape: (2, 3)
# Dimensions: 2
# Size: 6
# Data type: int64
# Item size: 8 bytes
# Total memory: 48 bytes
# Array content:
# [[1 2 3]
# [4 5 6]]
#
# === Analysis 3D ===
# Shape: (2, 2, 2)
# Dimensions: 3
# Size: 8
# Data type: int64
# Item size: 8 bytes
# Total memory: 64 bytesBefore passing an array to a model, check the shape, dtype, missing values, and memory footprint that the model actually expects.
import numpy as np
def validate_feature_matrix(arr):
"""Inspect a numeric feature matrix before modeling."""
print("=== ML Array Validation ===")
# Check dimensions
if arr.ndim != 2:
print(f"WARNING: Array is not 2D (current: {arr.ndim}D)")
else:
print(f"✓ 2D Array with shape: {arr.shape}")
# Check whether the matrix contains numeric values
if not np.issubdtype(arr.dtype, np.number):
print(f"WARNING: Data type may need conversion: {arr.dtype}")
return
print(f"✓ Numeric data type: {arr.dtype}")
# Check missing values (NaN)
if np.isnan(arr).any():
nan_count = np.isnan(arr).sum()
print(f"WARNING: Found {nan_count} NaN values")
else:
print("✓ No NaN values")
# Memory information
memory_mb = arr.nbytes / (1024 * 1024)
print(f"Memory usage: {memory_mb:.2f} MB")
# Test with various arrays
test_arrays = [
np.array([[1, 2, 3], [4, 5, 6]], dtype=np.float64),
np.array([1, 2, 3, 4, 5], dtype=np.int64),
np.array([[1, 2, np.nan], [4, 5, 6]], dtype=np.float64)
]
for i, arr in enumerate(test_arrays):
print(f"\n--- Test Array {i+1} ---")
validate_feature_matrix(arr)
# Output:
# --- Test Array 1 ---
# === ML Array Validation ===
# ✓ 2D Array with shape: (2, 3)
# ✓ Numeric data type: float64
# ✓ No NaN values
# Memory usage: 0.00 MB
#
# --- Test Array 2 ---
# === ML Array Validation ===
# WARNING: Array is not 2D (current: 1D)
# ✓ Numeric data type: int64
# ✓ No NaN values
# Memory usage: 0.00 MB
#
# --- Test Array 3 ---
# === ML Array Validation ===
# ✓ 2D Array with shape: (2, 3)
# ✓ Numeric data type: float64
# WARNING: Found 1 NaN values
# Memory usage: 0.00 MB