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
- Defining a structured dtype with named fields
- Type codes like 'U10', 'i4', and 'f8'
- Building an array from a list of tuples
- Accessing a field by name with data['age']
- Sorting records by a field with order=
- Using recarrays for data.age dot-access
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.0Expected 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.
| Task | Code |
|---|---|
| Define a dtype | np.dtype([('age', 'i4')]) |
| Read a field | data['age'] |
| Sort by a field | np.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
- Previous: Sorting, Searching & Counting
- Next: File I/O: save, load, savetxt — Persist arrays to .npy, .npz, and text files
- Quick reference: NumPy cheat sheet
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.