CodeMIRAI
0 XP

Shape, size and dtype

2 min read 6 runnable examples Quiz included

Every NumPy array has a shape (how many elements along each dimension) and a dtype (the one type all its elements share). Knowing both explains most of NumPy's behaviour.

Shape and dimensions

Python
import numpy as np

scalar = np.array(7)
vector = np.array([1, 2, 3])
matrix = np.array([[1, 2, 3],
                   [4, 5, 6]])
cube = np.zeros((2, 3, 4))     # 2 blocks of 3 rows by 4 columns

for name, arr in [("scalar", scalar), ("vector", vector), ("matrix", matrix), ("cube", cube)]:
    print(f"{name:7} ndim={arr.ndim}  shape={arr.shape}  size={arr.size}")
  • ndim is the number of dimensions, called axes.
  • shape is a tuple with the length along each axis: (2, 3) means 2 rows and 3 columns.
  • size is the total number of elements, the product of the shape.
  • len(arr) gives only the length of the first axis, which for the matrix is 2.

dtype

Python
import numpy as np

print(np.array([1, 2, 3]).dtype)            # a whole-number type, such as int64
print(np.array([1.5, 2, 3]).dtype)          # float64: one float makes them all floats
print(np.array([True, False]).dtype)        # bool
print(np.array(["cat", "horse"]).dtype)     # <U5: text of up to 5 characters
print(np.array([1, 2.5, "3"]))              # everything became text

An array holds one type. Mix types, and NumPy converts everything to the most general one, so a single float makes every element a float, and a single string makes every element a string. (The exact integer type can differ between systems; on most it's int64.)

Converting with astype

Python
import numpy as np

prices = np.array([19.99, 5.49, 120.0])
print(prices.astype(int))          # [ 19   5 120]: the decimals are cut off, not rounded
print(np.round(prices).astype(int))  # round first if that's what you mean

text = np.array(["10", "20", "35"])
numbers = text.astype(int)
print(numbers.sum())               # 65

flags = np.array([0, 3, 0, 1])
print(flags.astype(bool))          # zero is False, anything else is True

astype returns a new array of the requested type; the original is unchanged.

Fixed-size integers can overflow

Python
import numpy as np

small = np.array([100, 120, 127], dtype=np.int8)    # int8 holds -128 to 127
print(small + 10)                                   # silently wraps around

print(np.iinfo(np.int8))
print(np.iinfo(np.int64).max)

Unlike Python's own integers, which grow as large as needed, NumPy integers have a fixed size. Going past the limit wraps around without an error. The default 64-bit integers reach about 9.2 quintillion, so this mostly bites when you choose a small dtype to save memory.

Floating point isn't exact

Python
import numpy as np

a = np.array([0.1, 0.2])
print(a.sum() == 0.3)              # False!
print(a.sum())
print(np.isclose(a.sum(), 0.3))    # True: compare floats with a tolerance

Decimal fractions like 0.1 can't be stored exactly in binary, so tiny errors creep in. Compare floats with np.isclose, never with ==.

Memory

Python
import numpy as np

a = np.arange(1_000_000)
print(a.dtype, a.itemsize, "bytes each,", a.nbytes // 1_000_000, "MB in total")

b = a.astype(np.int32)
print(b.dtype, b.itemsize, "bytes each,", b.nbytes // 1_000_000, "MB in total")

itemsize is the size of one element and nbytes the size of the whole array. A smaller dtype halves the memory, which matters for big datasets, provided the values fit.

Finished this lesson?Mark it complete to earn +20 XP and move your progress on.