Enviar um café pro programador

Histograma em Python - Como gerar e plotar gráficos

 Neste tutorial, vamos aprender como gerar um gráfico do tipo histograma, através da linguagem de programação Python.

O que é um Histograma

Histograma é um tipo de gráfico, com barras verticais, onde cada uma represente uma classe de valores, e a altura representa a frequência que essa classe aparece no seu conjunto de dados. Numa linguagem mais técnica, representa uma distribuição de frequências.

Por exemplo, um consultório médico criou um histograma, para melhor entender a distribuição de idades dos pacientes:

Como plotar gráficos do tipo Histograma

No eixo x, temos as idades dos pacientes. Cada barra dessas representa uma idade ou intervalo de idades. Já o eixo y representa quantas vezes cada intervalo desses apareceu.

Pelo gráfico, podemos ver que cada barra dessas tem um intervalo próximo de 5 anos. A maior parte dos pacientes, tem por volta dos 20-25 anos e 25-30, pois cada barra que representa esses intervalos apareceu (frequência) mais de 50 vezes. Ou seja, tem mais de 100 pacientes com idade entre 20 e 30 anos.

Pacientes com mais de 90 anos? Bem poucos.
Pacientes com 0-5 anos de idade? Quase 20.

O gráfico do tipo histograma é muito útil quando você tem uma grande quantidade de dados e quer, rápida e facilmente, identificar como está a distribuição de determinados valores desses dados. Por ser uma maneira visual de representar e classificar dados, é muito usada para exibir resultados, seja em trabalhos científicos como em reuniões, por exemplo.

Tipos de Histograma em Python

Como podem imaginar, existe uma infinidade de tipos de gráficos histograma, e cada um deles nos diz informações muito importante sobre os dados que estamos analisando.

E, obviamente, o Python pode nos ajudar muito, mas muito mesmo, nessa tarefa de plotar e analisar.

Experimento do Pêndulo Simples

No laboratório de Física da Universidade Federal do Ceará (UFC), realizei o famoso experimento do pêndulo simples:

Pêndulo simples em Python

Cuja fórmula do período é dada por:

Física com Python

Onde L é o comprimento da corda do pêndulo, e g o valor da gravidade no local, que é 9,78 m/s² dentro do Campus do Pici, local onde foi realizado a medição.

Logo, o valor teórico do período é: T = 2,009141114 s = 2,01s
Vamos usar o mesmo número de algarismos significativos do cronômetro usado, dois.

Os valores que calculei podem ser obtidos em:
https://github.com/jarlissonmoreira/PythonProgressivo/blob/main/Histograma/data.txt

Note que os valores obtidos experimentalmente estão bem próximos do valor teórico. Vamos colocar esses valores em um histograma e ver isso em um gráfico, para confirmar que a maioria das medições estão ali por volta desse valor 2.01s

O meu arquivo tem 135 linhas, divididas em 10 colunas. Mas o script que será apresentado é bem abrangente, você pode colocar seus dados em quaisquer números de linhas e colunas, que ele vai funcionar.

Vamos aprender como usar o script para plotar um histograma.


Como plotar um Histograma em Python

Vamos usar a biblioteca matplotlib e a função hist() dela, para plotar nosso histograma.
Mas, antes, precisamos tratar nossos dados, antes de passar os valores para essa função.

De onde o script vai puxar esses dados? Onde e como você vai armazenar eles? Eles tem vírgula ou ponto, como decimal? Se for vírgula, precisa trocar por ponto. Como estão formatados? Tudo junto? Numa matriz? Em txt ou csv?

Usar as funções é fácil, o que devemos ter cuidado é na hora de tratar os dados.

No script fornecido abaixo, você pode passar os dados de várias maneiras. Eu, por exemplo, coloquei todos os dados no arquivo txt acima mencionado e em seguida usei o endereço desse arquivo "data.txt" (pois o data.txt está na mesma pasta do script histograma.py) para o parâmetro path da minha função plot_histograma().

Se preferir, pode passar diretamente os dados através do parâmetro data (como não usei, coloquei o valor None nele), fornecendo uma string de valores. Obviamente, só é viável se tiver poucos dados.

Por fim, precisamos configurar o bins, que são os intervalos das barras, no eixo x. Eu passei o valor 'auto', para a função hist() fazer o melhor ajuste possível, mas você pode definir manualmente os intervalos que desejar.

Vamos plotar três gráficos. O primeiro, é o histograma da matriz original, com todos os dados, bastando fazer:

  • ax1.hist(array, bins)

Onde array são os dados e bins os intervalos.

No segundo gráfico, vamos calcular as médias de cada linha da matriz. Nossa matriz tem 135 linhas com 10 elementos em cada. Logo, nosso segundo gráfico vai ter 135 elementos. Isso é muito usado em Física Experimental, a média das médias, pois fornecem valores mais confiáveis e próximos do teórico, pois 'amenizam' os resultados muito discrepantes.

Por fim, ploetei os dois gráficos juntos, um na frente do outro, para vermos a diferença.

O resultado ficou:

Script para fazer histograma em Python

Nosso script, usado para gerar esses plots de histogramas, é:

import numpy as np
from matplotlib import pyplot


def plot_histograma(path: str = None, data: str = None, bins: float | str = None) -> None:
    #path: caminho do arquivo .txt com os dados "caminho/do/data.txt"
    #bins: se nao fornecido retorna o histograma dos valores individuais,
    #ele pode ser tamanho (float), ou uma string com valores: 'auto', 'fd', 'doane', 'scott', 'stone', 'rice', 'sturges', or 'sqrt'
    #return: printa na tela o histograma
    
    if path is not None:
        with open(path, "r") as file:
            content = file.read().replace(',', '.')
            values: list[float] = [float(i) for i in content.split()]
    else:
        content = data.replace(',', '.')
        values: list[float] = [float(i) for i in content.split(';')]
   
    array = np.array(values)
    
    if bins is None:
        bins=sorted(values)
       
    if type(bins) is str:
        bins=bins
       
    if type(bins) is float:
        bins = np.arange(array.min(), array.max() + bins, bins)
    
    #Transforma o array/lista de valores em uma matriz com 10 colunas
    col = 10
    lin = int(len(array)/col)
    array2 = array.reshape(lin,col)
    
    #Cria um array, onde cada elemento é uma média de 10 valores,
    #de cada linha da matriz anterior
    median=np.mean(array2, axis=1)
    
    #Novo código para imprimir os três gráficos, com mesmo eixo x
    fig, (ax1, ax2, ax3) = pyplot.subplots(3, 1, sharex=True)

    #Primeiro gráfico, de 1350 medições
    ax1.hist(array, bins)
    ax1.xaxis.set_tick_params(labelbottom=True)
    leg1 = str(lin*col)
    ax1.set_xlabel(leg1+' medições')

    #Segundo gráfico, das 135 médias
    ax2.hist(median,bins)
    ax2.xaxis.set_tick_params(labelbottom=True)
    leg2 = str(len(median))
    ax2.set_xlabel(leg2+' médias')
    
    #Sobrepondo os dois, para efeitos de comparação
    ax3.hist(array, bins, alpha=0.5, label=leg1)
    ax3.hist(median, bins, alpha=0.5, label=leg2)
    ax3.set_xlabel('Gráficos sobrepostos')
    ax3.legend(loc='upper right')
    
    pyplot.tight_layout()
    pyplot.show()

path="data.txt"
data=None
bins='auto'
plot_histograma(path,data,bins)

Nenhum comentário:

Postar um comentário