Structured arrays, datetimes and string dtypes
Record-like arrays, calendar arithmetic with datetime64, and the fixed-width string type that quietly truncates your data.
Structured arrays
A structured array stores records with named fields in one contiguous buffer. It is the closest NumPy gets to a table, and fields are accessed by name and keep their own dtypes.
dt = np.dtype([("name", "U10"), ("age", "i4"), ("score", "f8")])
rows = np.array([("ada", 36, 91.5), ("bob", 41, 78.0)], dtype=dt)
rows["age"] # array([36, 41], dtype=int32)
rows[rows["age"] > 38] # boolean mask over a field
rows["score"].mean() # 84.75
np.sort(rows, order="score") # sort records by a field
rows[0] # a record, not a view
rows[0]["age"] = 37 # writes through to the buffer
rows["score"] = rows["score"] + 1 # update one field across all records| dtype code | Meaning | Example |
|---|---|---|
i4, f8 | Integers and floats | Compact numeric fields |
U10 | Unicode string, fixed width 10 | Short labels |
S10 | Bytes string, fixed width 10 | Legacy binary data |
M8[D] | Datetime64, day resolution | Calendar dates |
m8[s] | Timedelta64, second resolution | Durations |
O | Python object | Anything else, at a cost |
Datetime64 arithmetic
d = np.array(["2026-01-01", "2026-02-01"], dtype="datetime64[D]")
d + np.timedelta64(30, "D") # array with 30 days added
d[1] - d[0] # numpy.timedelta64(31,'D')
(d[1] - d[0]) / np.timedelta64(1, "D") # 31.0, a plain float
d.astype("datetime64[M]") # truncate to the month
np.datetime64("2026-09-18T12:00") # an instant
np.datetime64("now") # current time, second resolution
# a date axis for a plot or a group-by in seconds
stamps = np.array(["2026-01-01T00:00", "2026-01-01T01:30"], dtype="datetime64[m]")
stamps.astype("datetime64[h]")- The unit in the dtype decides precision: converting to a coarser unit truncates rather than rounds.
NaTis the missing-value marker;np.isnat(d)tests for it.- Subtracting two datetimes gives a timedelta, not a number; divide by a timedelta of the unit you want.
- Time zones are not represented: convert to UTC before storing.
String dtypes and their traps
s = np.array(["abc", "de"], dtype="U3") # fixed width, space padded
s.astype("U10") # widening is safe
np.char.upper(s) # vectorised string operations
np.char.add(s, "_x")
np.char.str_len(s)
np.array(["long text"], dtype="U3") # silently truncated to 'lon'
s.astype(object) # unlimited length, much slower⚠️
A fixed-width string dtype truncates on assignment without an error. If your array might contain names, URLs or free text, choose a generous width or use
dtype=object — and prefer pandas or Arrow for real text data.FAQ
Structured array or pandas DataFrame?
Use a structured array for compact binary records that stay in NumPy, especially when exported with
np.save. Use a DataFrame for labelled analysis, joins and mixed missing values.Why is datetime64 giving me an error on month arithmetic?
Arithmetic requires a timedelta, and adding months is not a fixed duration. Add
np.timedelta64(30, "D"), or convert to months and increment the integer.Related
File I/O: save, load, npz and memory-mapped arrays Sorting, searching and set operations
Last refreshed 2026-09-18.