Pular para o conteúdo principal

Análise exploratória de cervejas artesanais: data profiling

Neste tutorial, você vai aprender sobre análise exploratória de dados (EDA) em Python e, mais especificamente, data profiling com pandas.
Atualizado 17 de set. de 2026  · 14 min lido

Explorar com IA

ChatGPTClaudePerplexity

Nota do editor: Jean-Nicholas Hould é cientista de dados na Intel Security, em Montreal, e ensina como começar em ciência de dados no seu blog.

Análise exploratória de dados (EDA) é uma abordagem estatística voltada a descobrir e resumir um conjunto de dados. Nesta etapa do processo de ciência de dados, você explora a estrutura do seu dataset, as variáveis e seus relacionamentos.

Neste post, vamos focar em um aspecto da análise exploratória: o data profiling.

Data profiling é, essencialmente, resumir seu dataset por meio de estatísticas descritivas. A ideia é usar um conjunto amplo de medidas para entender melhor seus dados. Tipos de dados, valores ausentes, média, mediana e desvio padrão são apenas alguns dos muitos elementos que você precisa levantar ao fazer o perfil de um dataset. O objetivo é ter uma compreensão sólida dos dados para, depois, começar a consultar e visualizar de diferentes formas.

Saiba de onde vêm seus dados

Antes de mergulhar em qualquer EDA, procure saber o máximo possível sobre a procedência dos dados que você está analisando. Entenda como os dados foram coletados e processados. Há transformações anteriores que possam afetar sua análise?

Você deve conseguir responder perguntas como:

  • Como foi coletado?
  • É uma amostra?
  • Foi amostrado corretamente?
  • O dataset passou por alguma transformação?
  • Existem problemas conhecidos no dataset?

Se você não entende de onde os dados vêm, será difícil tirar conclusões significativas. Além disso, aumenta o risco de cometer erros importantes na análise.

Também vale checar se o dataset está estruturado de forma padronizada. O formato recomendado é a terceira forma normal, também chamada de tidy data. Um dataset “organizado” tem as seguintes características:

  • cada variável forma uma coluna e contém valores
  • cada observação forma uma linha
  • cada tipo de unidade observacional forma uma tabela

Seguir esse formato padronizado acelera sua análise, já que é compatível com muitas ferramentas e bibliotecas.

Data profiling

Neste post, usaremos um dataset de cervejas artesanais (Craft Beers) do site CraftCans. Esse dataset contém apenas dados de cervejas em lata de cervejarias dos Estados Unidos. Não está claro no site se ele cobre todas as cervejas enlatadas produzidas nos EUA. Para jogar seguro, vamos tratá-lo como uma amostra que pode conter vieses.

Esta é a estrutura dos datasets que você vai usar:

Beers:

  • ID: identificador único da cerveja.
  • Name: nome da cerveja.
  • ABV: teor alcoólico por volume da cerveja.
  • IBU: International Bittering Units da cerveja.
  • Style: estilo da cerveja.
  • Ounces: onças de cerveja.

Breweries:

  • ID: identificador único da cervejaria.
  • Name: nome da cervejaria.
  • City: cidade onde a cervejaria está localizada.
  • State: estado onde a cervejaria está localizada.

Tipos de dados

O primeiro passo é entender a composição do seu dataset.

Com quais variáveis você está lidando?

Em geral, os dados se encaixam em uma destas categorias:

  • numérico
  • categórico
  • texto
  • data

Primeiro, vamos importar os datasets disponíveis neste repositório com a função from_csv do pandas. Também vamos juntar os datasets beers e breweries para facilitar as análises depois.

import pandas as pd

beers = pd.DataFrame.from_csv("https://raw.githubusercontent.com/nickhould/craft-beers-dataset/master/data/craftcans_beers.csv")
breweries = pd.DataFrame.from_csv("https://raw.githubusercontent.com/nickhould/craft-beers-dataset/master/data/craftcans_breweries.csv")

beers_and_breweries = pd.merge(beers, 
                               breweries, 
                               how='inner', 
                               left_on="brewery_id", 
                               right_on="id", 
                               sort=True,
                               suffixes=('_beer', '_brewery'))

Com a biblioteca pandas, você pode usar a função dtypes para listar cada coluna e seus tipos de dados.

beers.dtypes

O resultado é o seguinte:

abv           float64
ibu           float64
id              int64
name           object
style          object
brewery_id      int64
ounces        float64
dtype: object

Como dá para ver, essa função não agrupa os diferentes tipos de forma muito clara. Os vários tipos numéricos (float64 e int64) não entram em uma única categoria, como gostaríamos. Além disso, algumas colunas aparecem como objetos, o que não ajuda muito.

Para contornar isso, você pode criar sua própria função para determinar a categoria de cada coluna em um DataFrame.

def get_var_category(series):
    unique_count = series.nunique(dropna=False)
    total_count = len(series)
    if pd.api.types.is_numeric_dtype(series):
        return 'Numerical'
    elif pd.api.types.is_datetime64_dtype(series):
        return 'Date'
    elif unique_count==total_count:
        return 'Text (Unique)'
    else:
        return 'Categorical'

def print_categories(df):
    for column_name in df.columns:
        print(column_name, ": ", get_var_category(df[column_name]))

Beers variáveis

print_categories(beers)

O comando acima retorna:

abv :  Numerical
ibu :  Numerical
id :  Numerical
name :  Categorical
style :  Categorical
brewery_id :  Numerical
ounces :  Numerical

Breweries variáveis

print_categories(breweries)

Que gera o seguinte resultado:

name :  Categorical
city :  Categorical
state :  Categorical
id :  Numerical

Com essas informações, você já entende melhor o dataset. Sabemos que estamos lidando apenas com dados categóricos e numéricos. Variáveis numéricas permitem extrair diversas medidas, como média, desvio padrão etc. Variáveis categóricas são ótimas para segmentar e agrupar os dados. Por exemplo, você pode querer entender como o IBU varia entre os diferentes estilos de cerveja.

Estatísticas descritivas

Nesta seção, vamos percorrer várias estatísticas descritivas que ajudam a entender melhor os dados. Note que cada medida, isoladamente, não diz muita coisa. É na combinação delas que você extrai mais valor.

Vamos focar na variável IBU por ser numérica. Esse tipo de variável oferece uma gama mais ampla de métricas do que as categóricas. Você até pode fazer medições em variáveis categóricas, mas com muito mais limitações.

Quantidade de observações

A função len conta o número de observações em uma Series. Ela conta todas as observações, independentemente de haver valores ausentes ou nulos.

length = len(beers["ibu"])
print(length)

Nesta Series, temos um total de 2410 observações.

Contagem (não nulos)

A função count retorna o número de observações não nulas em uma Series.

count = beers["ibu"].count()
print(count)

Como você vê, existem 1405 observações não nulas na Series.

Valores ausentes

Com a Length e a Count, conseguimos calcular o número de valores ausentes. É a diferença entre Length e Count.

number_of_missing_values = length - count
pct_of_missing_values = float(number_of_missing_values / length)
pct_of_missing_values = "{0:.1f}%".format(pct_of_missing_values*100)
print(pct_of_missing_values)

Para exibir a porcentagem de ausentes, basta dividir o número de valores ausentes pelo total de observações (length). A função float garante que os decimais sejam considerados na divisão. A função format formata o número como porcentagem.

Neste caso, faltam quase 42% dos valores de IBU. Isso é importante porque vai afetar sua análise. A maioria das estatísticas descritivas ignora valores ausentes, o que certamente pode introduzir viés.

Valor mínimo/máximo

Os valores mínimo e máximo podem ser obtidos facilmente com as funções min e max em uma Series.

print("Minimum value: ", beers["ibu"].min())
print("Maximum value: ", beers["ibu"].max())

Os valores mínimo/máximo ajudam a entender a faixa de uma variável. Aqui, o IBU vai de 4 a 138.

Moda

A moda é o valor mais frequente em um dataset. Você a obtém com a função mode em uma Series.

print(beers["ibu"].mode())

Em uma distribuição normal, a moda é igual à mean e à median.

Neste caso, a moda da variável IBU é 20. É o IBU mais frequente no dataset.

Média

A média é uma medida de tendência central. Representa a soma dos valores dividida pela contagem de observações não ausentes.

Pode ser obtida com a função mean em uma Series.

mean = beers["ibu"].mean()

A média é sensível a outliers. Alguns valores extremos podem puxá-la para cima ou para baixo.

Mediana

A mediana também é uma medida de tendência central. É o valor exatamente no meio de uma lista ordenada de valores numéricos.

median = beers["ibu"].median()

Em distribuições assimétricas, a mediana é uma medida melhor de tendência central do que a média.

No caso da distribuição de IBU, média e mediana estão na mesma ordem de grandeza.

Desvio padrão

O desvio padrão é uma medida de dispersão. Um desvio padrão alto indica que os pontos estão espalhados por uma faixa ampla de valores. Ele é expresso na mesma unidade dos valores.

standarddev = beers["ibu"].std()

Neste caso, o desvio padrão é ~26 (25.954065911259324, para ser exato). Se a distribuição de IBU fosse normal, ~68% das observações estariam a uma distância de um desvio padrão da média.

Estatísticas de quantis

Quantis são pontos de corte que dividem uma distribuição em partes iguais. Muitos quantis têm nome próprio. Ao dividir em quatro grupos iguais, temos os quartiles. É fácil calcular quantis com a função quantile em uma Series. Você passa um array com os quantis desejados. Abaixo, vamos dividir em quatro grupos iguais.

quantile = beers["ibu"].quantile([.25, .5, .75])
0.25 21.0
0.50 35.0
0.75 64.0
Name: ibu, dtype: float64

Como você vê, o quantil de 50% é igual à mediana: o valor que divide o dataset ao meio. Note também que 75% das observações são menores ou iguais a 64 IBU. Além disso, 50% da distribuição está entre 21 e 64 IBU. Importante: valores ausentes não entram nesses cálculos.

Gráficos de distribuição

Visualizações são muito úteis na análise exploratória. Aqui não vamos aprofundar o tema visualização, mas não dá para falar de data profiling sem mencionar a importância de um gráfico de distribuição de frequências. É uma das visualizações mais simples e poderosas: mostra a frequência de cada valor no dataset.

Para criar essa visualização, usamos a biblioteca seaborn com a função displot. Essa função espera uma Series sem valores ausentes.

import seaborn as sns
sns.set(color_codes=True)
sns.set_palette(sns.color_palette("muted"))

sns.distplot(beers["ibu"].dropna());

distribution plot

Nesse gráfico, dá para ver claramente alguns dos valores que calculamos. O mínimo fica perto de 0 IBU e o máximo perto de 140 IBU. A moda fica perto de 20 IBU. Além disso, aparece um pico próximo de 60 IBU.

Por que há dois picos nessa distribuição?

O que explica isso? Esse é um ponto para explorar na segunda fase da análise exploratória.

Correlação

Correlação é ótima para descobrir relações entre variáveis numéricas. Há várias formas de calculá-la. O coeficiente de correlação de Pearson é amplamente usado e mede a dependência linear entre duas variáveis. O coeficiente varia de -1 a 1: 1 é correlação totalmente positiva, -1 é totalmente negativa e 0 indica ausência de correlação linear. Podemos calcular isso com a função corr em um Series. Por padrão, ela usa Pearson, mas é possível escolher outros métodos.

beers[["abv", "ibu", "ounces"]].corr()
  abv ibu ounces
abv 1 0.670621 0.172529
ibu 0.670621 1 0.054691
ounces 0.172529 0.054691 1

Como esperado, a correlação de IBU com ele mesmo é 1. Mais interessante: a correlação entre ABV e IBU é 0.670621. Não é uma correlação perfeita, mas é alta. Vale explorar esse ponto mais a fundo.

Algumas notas sobre variáveis não numéricas

As métricas acima valem, em sua maioria, para valores numéricos. Se você estiver lidando com dados de outros tipos, como categóricos, ainda dá para coletar medidas interessantes. Por exemplo, calcular a frequência de cada valor no dataset.

DataFrames têm a função describe, que resume o dataset. Se o seu DataFrame tiver apenas valores categóricos ou de texto, o resumo será adaptado para esse tipo de dado.

beers[["name", "style"]].describe()
  name style
count 2410 2405
unique 2305 99
top Nonstop Hef Hop American IPA
freq 12 424

Bibliotecas para profiling

Como você viu, coletar estatísticas descritivas pode ser trabalhoso. Felizmente, existem bibliotecas que fazem esse processamento para você e geram um perfil claro dos seus dados. Uma delas é a pandas-profiling, que oferece profiling estatístico pronto para uso. Como nosso dataset está organizado e padronizado, podemos aplicar a biblioteca diretamente.

import pandas_profiling 

pandas_profiling.ProfileReport(beers_and_breweries)

Mais perguntas

Em geral, depois de fazer o profiling do dataset, você termina com muito mais perguntas do que no início. Ótimo: essas novas perguntas vão impulsionar sua análise exploratória.

Aqui vão algumas questões que surgiram durante o profiling:

  • 41,7% dos valores de IBU estão ausentes. Por quê? Como isso pode afetar nossa análise?
  • Há dois picos na distribuição de IBU. O que explica isso?
  • O que explica a correlação entre IBU e ABV? Qual é a influência do estilo da cerveja nessa correlação?
  • Existem diferenças de IBU, ABV ou Style entre regiões geográficas? E entre East Coast e West Coast?

Data profiling não é um processo linear. À medida que você filtra e segmenta o dataset, vai voltar a ele e coletar estatísticas descritivas em subgrupos.

Próximos passos

Neste post, você viu como fazer o perfil de um dataset. Agora você sabe como atribuir variáveis a grupos de tipos de dados específicos. Também calculou diferentes estatísticas descritivas e entende como interpretá-las. Por fim, conheceu bibliotecas que ajudam a automatizar o profiling. E, mais importante, gerou novas perguntas para turbinar sua análise exploratória.

Confira o tutorial de análise exploratória de dados em Python da DataCamp.

Tópicos
Data Analysis
Ciência de dados
Python

Saiba mais sobre Python

Curso

Análise de Dados Bayesiana em Python

4 h
16.1K
Aprenda tudo sobre as vantagens da análise de dados bayesiana e aplique-a em vários casos de uso do mundo real!
Ver detalhesRight Arrow
Iniciar Curso
Ver maisRight Arrow
Relacionado
Data Analyst surfing on wave of data

blog

9 Habilidades essenciais do analista de dados: Um guia de carreira abrangente

Aprenda habilidades essenciais de analista de dados, tanto técnicas quanto interpessoais, desde programação em Python até comunicação eficaz, para avançar em sua carreira.
Matt Crabtree's photo

Matt Crabtree

9 min

Tutorial

Perfilamento do Pandas (ydata-profiling) em Python: Um guia para iniciantes

Saiba como usar a biblioteca ydata-profiling em Python para gerar relatórios detalhados para conjuntos de dados com muitos recursos.
Satyam Tripathi's photo

Satyam Tripathi

9 min

data-frames-in-python-banner_cgzjxy.jpeg

Tutorial

Pandas Tutorial: DataFrames em Python

Explore a análise de dados com Python. Os DataFrames do Pandas facilitam a manipulação de seus dados, desde a seleção ou substituição de colunas e índices até a remodelagem dos dados.
Karlijn Willems's photo

Karlijn Willems

15 min

Tutorial

Tutorial do Python pandas: O guia definitivo para iniciantes

Você está pronto para começar sua jornada com os pandas? Aqui está um guia passo a passo sobre como você pode começar.
Vidhi Chugh's photo

Vidhi Chugh

15 min

Tutorial

Tutorial de junção de DataFrames no pandas

Neste tutorial, você aprenderá várias maneiras pelas quais vários DataFrames podem ser mesclados em python usando a biblioteca Pandas.
DataCamp Team's photo

DataCamp Team

13 min

Tutorial

Tutorial de seleção de colunas em Python

Use o Python Pandas e selecione colunas de DataFrames. Siga nosso tutorial com exemplos de código e aprenda diferentes maneiras de selecionar seus dados hoje mesmo!
DataCamp Team's photo

DataCamp Team

7 min

Ver MaisVer Mais