Structured & Record Arrays

Reviewed & published by Brayan K

A structured array is a NumPy array whose elements are records built from several named fields, each with its own data type — letting you keep table-like, mixed-type data (a string name, an integer age, a float height) inside one fast ndarray. In this lesson you'll define a structured dtype, build an array from a list of tuples, read fields by name, sort by a field, and meet recarrays, which add convenient dot-access.

Part of the free NumPy course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

What You'll Learn in This Lesson

1 Defining a Structured dtype

A normal NumPy array holds a single type for every element. A structured array instead gives each element several named fields, each with its own type. You describe that layout with a structured dtype — a list of (name, type) tuples.

Common type codes: 'U10' is a Unicode string up to 10 characters, 'i4' is a 4-byte integer, and 'f8' is an 8-byte float.

import numpy as np

# Describe a record: a name, an age, and a height
person_dtype = np.dtype([('name', 'U10'), ('age', 'i4'), ('height', 'f8')])
print(person_dtype.names)   # ('name', 'age', 'height')

# ✅ Expected output:
# ('name', 'age', 'height')

Expected output: the field names ('name', 'age', 'height').

2 Building an Array from Tuples

Once you have a dtype, build the array from a list of tuples — one tuple per record, with the values in field order. NumPy stores all the records together in fast, contiguous memory.

import numpy as np

person_dtype = np.dtype([('name', 'U10'), ('age', 'i4'), ('height', 'f8')])

people = np.array([
    ('Alice', 30, 1.65),
    ('Bob',   25, 1.80),
    ('Cara',  35, 1.70),
], dtype=person_dtype)

print(people)
# [('Alice', 30, 1.65) ('Bob', 25, 1.8 ) ('Cara', 35, 1.7 )]

print(people.shape)   # (3,)  -> three records, each with 3 fields

# ✅ Expected output:
# [('Alice', 30, 1.65) ('Bob', 25, 1.8 ) ('Cara', 35, 1.7 )]
# (3,)

Expected output: the three records and a shape of (3,) — three records, each with 3 fields.

3 Accessing Fields by Name

Index a structured array with a field name to pull that whole column out as a regular array. This is where structured arrays shine: you can run normal vectorized math on a single field.

import numpy as np

person_dtype = np.dtype([('name', 'U10'), ('age', 'i4'), ('height', 'f8')])
people = np.array([
    ('Alice', 30, 1.65),
    ('Bob',   25, 1.80),
    ('Cara',  35, 1.70),
], dtype=person_dtype)

# Pull out one field as a normal array
print(people['age'])        # [30 25 35]
print(people['name'])       # ['Alice' 'Bob' 'Cara']

# Vectorized math works on a single field
print(people['age'].mean()) # 30.0

# ✅ Expected output:
# [30 25 35]
# ['Alice' 'Bob' 'Cara']
# 30.0

Expected output: [30 25 35], the names array, and the mean age 30.0.

4 Sorting by a Field & Recarrays

To sort whole records by one field, pass order='fieldname' to np.sort. You can even pass a list of fields to break ties — NumPy sorts by the first, then the second, and so on.

import numpy as np

person_dtype = np.dtype([('name', 'U10'), ('age', 'i4'), ('height', 'f8')])
people = np.array([
    ('Alice', 30, 1.65),
    ('Bob',   25, 1.80),
    ('Cara',  35, 1.70),
], dtype=person_dtype)

# Sort the records by age (ascending)
by_age = np.sort(people, order='age')
print(by_age['name'])   # ['Bob' 'Alice' 'Cara']
print(by_age['age'])    # [25 30 35]

# ✅ Expected output:
# ['Bob' 'Alice' 'Cara']
# [25 30 35]

Expected output: names in age order ['Bob' 'Alice' 'Cara'] and ages [25 30 35].

A recarray is a structured array with a small convenience: you can read a field with attribute syntax — data.age instead of data['age']. Create one with np.rec.array. The underlying data is identical; only the access style changes.

import numpy as np

person_dtype = np.dtype([('name', 'U10'), ('age', 'i4'), ('height', 'f8')])

people = np.rec.array([
    ('Alice', 30, 1.65),
    ('Bob',   25, 1.80),
    ('Cara',  35, 1.70),
], dtype=person_dtype)

# Attribute access — note the dot, not brackets
print(people.name)    # ['Alice' 'Bob' 'Cara']
print(people.age)     # [30 25 35]

# ✅ Expected output:
# ['Alice' 'Bob' 'Cara']
# [30 25 35]

Expected output: the names array and the ages [30 25 35], read with dot-access.

🎯 YOUR TURN: Fill in the Blanks

Replace each ___ so the program builds a structured array, reads the score field, and sorts the records by score.

import numpy as np

# Two fields: a player name and an integer score
dt = np.dtype([('player', 'U10'), ('score', '___')])   # fill in the int type code

games = np.array([
    ('Mia', 70),
    ('Leo', 95),
    ('Sam', 80),
], dtype=dt)

# Read just the score field
print(games[___])                 # fill in the field name -> [70 95 80]

# Sort records by score
ranked = np.sort(games, order='___')   # fill in the field to sort by
print(ranked['player'])           # ['Mia' 'Sam' 'Leo']

Expected output: [70 95 80] then ['Mia' 'Sam' 'Leo']. (Answers: 'i4', 'score', score.)

⚠️ Common Errors & Quick Reference

❌ Strings get silently truncated

A field typed 'U5' stores only 5 characters, so 'Alexander' becomes 'Alexa'.

✅ Fix: make the width big enough, e.g. 'U20', for your longest expected string.

❌ IndexError / wrong values when using lists instead of tuples

Each record must be a tuple like ('Bob', 25, 1.8), not a list.

✅ Fix: wrap each record in parentheses and pass the matching dtype.

TaskCode
Define a dtypenp.dtype([('age', 'i4')])
Read a fielddata['age']
Sort by a fieldnp.sort(data, order='age')
Dot-access (recarray)np.rec.array(...).age

🏆 Mini Challenge: Tallest Person

Build a structured array of people and print the name of the tallest one using np.argmax on the height field.

import numpy as np

dt = np.dtype([('name', 'U10'), ('age', 'i4'), ('height', 'f8')])
people = np.array([
    ('Alice', 30, 1.65),
    ('Bob',   25, 1.80),
    ('Cara',  35, 1.70),
], dtype=dt)

# Index of the maximum height, then look up that name
tallest_idx = np.argmax(people['height'])
print(people['name'][tallest_idx])   # Bob

# ✅ Expected output:
# Bob

❓ Frequently Asked Questions

Lesson complete — you can build table-like arrays!

You defined a structured dtype, built records from tuples, read fields by name, sorted by a field, and used a recarray for convenient dot-access.

Practice quiz

What does a structured dtype let you store in one ndarray?

  • Only floats of one size
  • Records with several named fields, each its own type
  • A single Python dictionary
  • Strings only

Answer: Records with several named fields, each its own type. A structured array gives each element named fields, each with its own data type.

How do you describe a structured dtype layout?

  • A list of (name, type) tuples
  • A single string
  • A NumPy matrix
  • A set of integers

Answer: A list of (name, type) tuples. You pass a list like [('name','U10'), ('age','i4'), ('height','f8')].

What does the type code 'U10' mean?

  • A 10-byte integer
  • 10 floats
  • A Unicode string up to 10 characters
  • 10-dimensional array

Answer: A Unicode string up to 10 characters. 'U10' is a Unicode string of up to 10 characters.

Each record in the array passed to np.array must be a what?

  • A list
  • A dictionary
  • A NumPy array
  • A tuple

Answer: A tuple. Records are tuples like ('Bob', 25, 1.8), matching the dtype field order.

How do you pull the 'age' field out as a regular array?

  • people['age']
  • people.field('age')
  • people(age)
  • age(people)

Answer: people['age']. Indexing with a field name returns that whole column as a normal array.

What does np.sort(people, order='age') do?

  • Sorts only the age field in place
  • Sorts whole records by the age field
  • Deletes the age field
  • Reverses every field

Answer: Sorts whole records by the age field. order= sorts the entire records by the named field.

What is the shape of an array built from 3 records of 3 fields each?

  • (3, 3)
  • (9,)
  • (3,)
  • (1, 3)

Answer: (3,). It is (3,) — three records, each holding 3 fields, not a 2D array.

How do you create a recarray for dot-access?

  • np.array(...)
  • np.dtype(...)
  • np.records(...)
  • np.rec.array(...)

Answer: np.rec.array(...). np.rec.array builds a recarray that supports data.age attribute access.

On a recarray, how do you read the age field with dot-access?

  • data['age']
  • data.age
  • data->age
  • data:age

Answer: data.age. Recarrays add attribute access, so data.age works like data['age'].

If a field is typed 'U5', what happens to 'Alexander'?

  • It raises an error
  • It stays full length
  • It is truncated to 'Alexa'
  • It becomes empty

Answer: It is truncated to 'Alexa'. 'U5' stores only 5 characters, silently truncating to 'Alexa'.

Continue this course

Frequently asked questions

What is a structured array in NumPy?

A structured array is an ndarray whose elements are records made of several named fields, each with its own data type. It lets you store heterogeneous, table-like data — for example a name string, an integer age, and a float height — in a single, fast NumPy array.

How do I define the dtype for a structured array?

Pass a list of (name, type) tuples as the dtype, for example dtype=[('name', 'U10'), ('age', 'i4'), ('height', 'f8')]. 'U10' is a Unicode string up to 10 characters, 'i4' is a 4-byte integer, and 'f8' is an 8-byte float.

Can I sort a structured array by one field?

Yes. Use np.sort(data, order='age') to sort by a single field, or pass a list like order=['age', 'height'] to sort by several fields in priority order. A recarray created with np.rec.array works the same way but also lets you read fields with dot-access like data.age.