Pular para o conteúdo

    Capítulo 26, Intermediário

    Tipos estruturados e datas

    Um array tem um tipo só, mas esse tipo pode ser composto (um "registro" com campos) ou ser uma data. Os dois resolvem problemas reais, e mostram até onde o NumPy vai antes de o pandas fazer sentido.

    Código deste capítulo: intermediario/cap26_estruturados_datas.py

    Registros com campos

    Um dtype estruturado define campos com nome e tipo, e cada elemento do array é um registro. Dá para ler um campo inteiro como um array comum, filtrar e ordenar por campo:

    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"])
    
    Saída
    ['Ana' 'Bia'] 27.5
    [('Ana', 30, 1.65)]
    ('nome', 'idade', 'altura') 52
    ['Bia' 'Ana']
    

    O itemsize é a soma dos campos: 40 bytes do nome (U10 são 10 caracteres de 4 bytes), 4 da idade e 8 da altura. Os registros ficam contíguos na memória, o que é bom para ler e gravar, e o acesso por campo é rápido.

    Quando o conjunto de dados tem muitas colunas, tipos variados ou precisa de rótulos, o DataFrame do pandas faz tudo isso com mais conforto, e o NumPy estruturado é mais usado em interface com formatos binários e com código em C.

    Datas e durações

    O datetime64 guarda datas como números inteiros, com uma unidade que você escolhe (D para dias, M para meses, s para segundos). O timedelta64 guarda durações. A subtração de duas datas dá uma duração, e somar uma duração a uma data dá outra data:

    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"))
    
    Saída
    ['2026-01-15' '2026-02-20'] datetime64[D]
    36 days
    2026-03-31
    

    Sequências de datas e conversão de unidade

    O arange funciona com datas. E o astype troca a unidade, o que é útil para agrupar por mês:

    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]"))
    
    Saída
    ['2026-01-01' '2026-01-02' '2026-01-03' '2026-01-04' '2026-01-05']
    ['2026-01' '2026-02']
    

    Dias úteis

    O NumPy conhece o calendário de dias úteis (segunda a sexta, por padrão), e conta e soma dias úteis diretamente. Feriados entram como uma lista:

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

    De 1º a 30 de outubro de 2026 (o fim é excluído) existem 22 dias úteis.

    Fusos horários

    O datetime64 não tem fuso horário: ele guarda um instante sem dizer em que fuso ele está. Para trabalhar com fusos, use o módulo datetime com timezone/zoneinfo (capítulo 39 do curso de Python) ou o pandas, e guarde tudo em UTC.

    Exercício 1

    Dias entre duas datas

    Escreva dias_entre(inicio, fim) que receba duas datas no formato "2026-01-01" e devolva a quantidade de dias como um inteiro Python.