Skip to content

    Chapter 26, Intermediate

    Structured types and dates

    An array has only one type, but this type can be composite (a "record" with fields) or be a date. Both solve real problems and show how far NumPy goes before pandas makes sense.

    Code for this chapter: intermediario/cap26_estruturados_datas.py

    Records with fields

    A structured dtype defines fields with name and type, and each element of the array is a record. You can read an integer field like a common array, filter and sort by field:

    intermediario/cap26_estruturados_datas.pylinhas 10 a 19
    import numpy as np
    
    pessoas = np.array(
        [("Ana", 30, 1.65), ("Bia", 25, 1.70)],
        dtype=[("nome", "U10"), ("idade", "i4"), ("altura", "f8")],
    )
    print(pessoas["nome"], pessoas["idade"].mean())
    print(pessoas[pessoas["idade"] > 26])
    print(pessoas.dtype.names, pessoas.itemsize)
    print(np.sort(pessoas, order="idade")["nome"])
    
    Output
    ['Ana' 'Bia'] 27.5
    [('Ana', 30, 1.65)]
    ('nome', 'idade', 'altura') 52
    ['Bia' 'Ana']
    

    The itemsize is the sum of the fields: 40 bytes for the name (U10 are 10 characters of 4 bytes), 4 for age and 8 for height. The records are contiguous in memory, which is good for reading and writing, and access by field is fast.

    When the dataset has many columns, varied types, or needs labels, the DataFrame from pandas does all this more comfortably, and structured NumPy is more used in interface with binary formats and with C code.

    Dates and durations

    The datetime64 stores dates as integers, with a unit that you choose (D for days, M for months, s for seconds). The timedelta64 stores durations. Subtracting two dates gives a duration, and adding a duration to a date gives another date:

    intermediario/cap26_estruturados_datas.pylinhas 24 a 27
    d = np.array(["2026-01-15", "2026-02-20"], dtype="datetime64[D]")
    print(d, d.dtype)
    print(d[1] - d[0])
    print(np.datetime64("2026-03-01") + np.timedelta64(30, "D"))
    
    Output
    ['2026-01-15' '2026-02-20'] datetime64[D]
    36 days
    2026-03-31
    

    Date sequences and unit conversion

    The arange works with dates. And the astype changes the unit, which is useful for grouping by month:

    intermediario/cap26_estruturados_datas.pylinhas 32 a 33
    print(np.arange("2026-01-01", "2026-01-06", dtype="datetime64[D]"))
    print(d.astype("datetime64[M]"))
    
    Output
    ['2026-01-01' '2026-01-02' '2026-01-03' '2026-01-04' '2026-01-05']
    ['2026-01' '2026-02']
    

    Business days

    NumPy knows the calendar of business days (Monday to Friday, by default), and counts and sums business days directly. Holidays are included as a list:

    intermediario/cap26_estruturados_datas.pylinha 38
    print(np.busday_count("2026-10-01", "2026-10-31"))
    
    Output
    22
    

    From October 1 to 30, 2026 (the end is excluded), there are 22 business days.

    Time zones

    The datetime64 has no time zone: it stores a moment without specifying which time zone it is in. To work with time zones, use the module datetime with timezone/zoneinfo (chapter 39 of the Python course) or pandas, and store everything in UTC.

    Exercise 1

    Days between two dates

    Write dias_entre(inicio, fim) that receives two dates in the format "2026-01-01" and returns the number of days as a Python integer.