Estatística em Python: Usando Pandas para compreensão de sua distribuição

, updated •0•0Comment iconComment iconComment iconComment icon

Use o pandas para calcular média, mediana, moda, desvio padrão, CV, assimetria e curtose, fazer histograma e boxplot e transformar dados com logaritmo.

Artikel bewerken

Material para acompanhar esta aula

Baixe a planilha encontrada aqui no Google Planilhaslink outside website. Usaremos esta planilha durante a aula. Baixe-a no formato CSV (Comma-Separated Values, valores separados por vírgula), o formato mais comum para guardar uma tabela de dados que pode ser lida por qualquer linguagem.

Crie um ambiente de desenvolvimento Python 3 ou use um ambiente online já pronto, como o jupyter lab onlinelink outside website, e carregue o arquivo nele.

Os números da planilha usam vírgula decimal, como 0,0177. O que acontece se você ler o CSV com pd.read_csv sem o argumento decimal=','?

Loading icon

Gabarito: As colunas com vírgula são lidas como texto, e .mean() passa a dar erro — o pandas assume o ponto como separador decimal; um valor como 0,0177 vira a palavra '0,0177', e no pandas atual a média dessa coluna gera TypeError. O pandas não adivinha o separador decimal: é preciso informá-lo.

Pandas em Python

Se você usar a versão online, sua pasta ficará assim:

Pasta no jupyter lab online
Pasta no jupyter lab online

Vamos usar o pandas para entender nossa base de dados. Para importá-lo (junto com o numpy e o matplotlib, que usaremos adiante), use:

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

E vamos abrir a base de dados com read_csv:

df = pd.read_csv("Trabalho de Estatística 1 - Set de dados.csv", decimal=',')

Lembre-se de usar decimal="," ou o pandas não reconhecerá como números os valores escritos com vírgula: por padrão, o Python assume o ponto como separador decimal, como se escreve nos Estados Unidos, e não a vírgula, como se escreve no Brasil.

Agora use .info() ou .describe() na tabela para obter um resumo rápido de cada coluna (contagem de valores não nulos, média, desvio padrão, mínimo, quartis e máximo):

Exemplo com .describe()
Exemplo com .describe()

Nos exemplos a seguir trabalharemos com a coluna "22" (column = "22"). Para calcular a média, a mediana e a moda, use respectivamente .mean(), .median() e .mode():

Cálculo da média, moda e mediana em pandas
Cálculo da média, moda e mediana em pandas

Repare no erro da imagem: .mean() e .median() devolvem um único número, mas .mode() devolve sempre uma lista de valores (uma Series), porque pode haver mais de uma moda. Por isso o formato :.2f dentro da f-string, que só serve para um número, falha com TypeError. Para mostrar todas as modas, use:

moda_total = df[column].mode()
print("Moda(s):", moda_total.tolist())

Nesta coluna há duas modas (1.033.106.135 e 1.766.383.450). Em dados contínuos como estes, a moda costuma ser pouco informativa: são apenas valores que se repetiram por acaso.

O desvio padrão e o coeficiente de variação (CV = desvio padrão ÷ média) podem ser calculados assim:

Desvio padrão e CV no pandas
Desvio padrão e CV no pandas

O .std() do pandas usa o desvio padrão amostral (divide por \( n-1 \)). Um CV de 301% mostra que os dados são extremamente dispersos em relação à média.

Agora vamos calcular a assimetria:

Assimetria em Pandas
Assimetria em Pandas

A fórmula usada pelo .skew() do pandas é o coeficiente de assimetria de Fisher-Pearson ajustado para amostras:

\[ G_1 = \frac{n}{(n-1)(n-2)} \sum_{i=1}^n \left( \frac{x_i - \bar{x}}{s} \right)^3 \]

Onde:

  • \( n \) = número de observações (os valores ausentes, NaN, são ignorados);
  • \( x_i \) = cada valor individual;
  • \( \bar{x} \) = média amostral;
  • \( s \) = desvio padrão amostral (com \( n-1 \) no denominador).

O fator \( \frac{n}{(n-1)(n-2)} \) corrige o viés da medida em amostras pequenas. A segunda célula da imagem usa outra medida, o coeficiente de assimetria de Pearson, \( 3(\bar{x} - \text{mediana})/s \), que compara média e mediana. As duas medidas dão números diferentes (4,80 e 0,96 nesta coluna), mas concordam no sinal: a distribuição é assimétrica à direita. Os limites de 0,4 usados na imagem são apenas uma regra prática para dizer se a assimetria é relevante.

Agora o cálculo da curtose:

Curtose em pandas
Curtose em pandas

O .kurtosis() do pandas devolve a curtose em excesso (também com correção para amostras), ou seja, já subtrai a curtose da normal:

\[ G_2 = \frac{n(n+1)}{(n-1)(n-2)(n-3)} \sum_{i=1}^n \left( \frac{x_i - \bar{x}}{s} \right)^4 - \frac{3(n-1)^2}{(n-2)(n-3)} \]

Por isso a referência é 0, e não 3: uma normal tem curtose em excesso 0, valores positivos indicam distribuição leptocúrtica (caudas pesadas) e valores negativos, platicúrtica. O valor 26,40 mostra caudas muito mais pesadas que as da normal.

Agora vamos desenhar a distribuição com um histograma:

Use matplotlib para criar o histograma em python
Use matplotlib para criar o histograma em python

O trecho "if 'kde' in locals()..." da imagem pode ser apagado: nenhuma variável kde foi criada, então ele nunca é executado. O gráfico final:

Gráfico construído pelo matplotlib
Gráfico construído pelo matplotlib

Que forma de curva você enxerga? Aqui vejo uma curva em J invertido: a maior frequência está no começo (perto de zero) e a frequência cai rapidamente, com uma cauda longa à direita. Repare também como a média (286,8 milhões) fica muito acima da mediana (9,9 milhões), puxada pelos valores extremos.

Você também pode fazer um boxplot para ver seus dados:

Boxplot no matplotlib
Boxplot no matplotlib

O dropna da imagem é necessário porque o boxplot do matplotlib não ignora valores ausentes. Repare, porém, que o boxplot ajuda pouco em curvas em J invertido: a caixa fica espremida perto de zero e dezenas de pontos aparecem como valores atípicos.

Na coluna 22, a média é 286,8 milhões e a mediana é 9,9 milhões. O que essa diferença indica?

Loading icon

Gabarito: Assimetria à direita, com uma cauda longa de valores altos que puxa a média para cima — a mediana depende só da posição central, enquanto a média é arrastada pelos valores extremos. Na assimetria à esquerda seria o contrário: média abaixo da mediana.

O comando df[column].kurtosis() do pandas devolveu 26,40. Como interpretar esse número?

Loading icon

Gabarito: Leptocúrtica: o pandas mede a curtose em excesso, cuja referência normal é 0, e 26,40 indica caudas muito pesadas — o erro mais comum é comparar o resultado do pandas com 3, que é a referência da curtose sem a subtração.

Transformando seus dados

Como a curva tem a forma de J invertido, podemos transformar os dados para aproximá-los de uma curva em forma de sino, que é mais fácil de trabalhar. Neste caso vou usar o logaritmo (np.log, que exige o import numpy as np feito no início):

Transformação para logaritmo em pandas
Transformação para logaritmo em pandas

A transformação pode ser feita de várias maneiras: podemos tirar o logaritmo, a raiz quadrada, entre outras. Aqui escolhi o logaritmo porque a cauda à direita é muito acentuada e a coluna não tem zeros nem valores negativos (o logaritmo de zero é menos infinito). Costumamos usar o logaritmo em valores financeiros (salários, preços de ações), tamanhos de população, tempos de resposta de sistemas e dados de vendas com valores atípicos positivos. Já a raiz quadrada costuma servir para contagens: número de visitas a sites, de acidentes, de produtos vendidos e outras frequências de eventos, inclusive quando há zeros.

Histograma da distribuição log transformada
Histograma da distribuição log transformada

Pelo histograma, parece que acertamos na transformação!

Boxplot da Log Transformada
Boxplot da Log Transformada

Os números confirmam: depois do logaritmo, a média (16,14) e a mediana (16,10) praticamente coincidem, o desvio padrão é 3,03, a assimetria cai de 4,80 para −0,03 (quase simétrica) e a curtose em excesso cai de 26,40 para −0,49 (levemente platicúrtica, ou seja, perto da normal). Para comparar, a raiz quadrada nesta coluna ainda deixa assimetria de 2,64: aqui o logaritmo foi mesmo a melhor escolha.

A coluna 4 da planilha tem 25 valores iguais a zero. O que acontece se você aplicar np.log nessa coluna?

Loading icon

Gabarito: Os zeros viram menos infinito, e as médias e gráficos da coluna transformada ficam inválidos — o logaritmo de zero não existe. Nesses casos use a raiz quadrada ou np.log1p, que calcula o logaritmo de 1 + x.

Depois do logaritmo, a coluna 22 ficou com assimetria −0,03 e curtose em excesso −0,49. O que isso indica?

Loading icon

Gabarito: Que a distribuição ficou praticamente simétrica e com caudas próximas às da normal — assimetria perto de 0 é simetria, e curtose em excesso de −0,49 é apenas levemente platicúrtica. Assimetria à esquerda exigiria um valor claramente negativo, como −1.

Trabalho: faça você mesmo!

Escolha uma coluna da base de dados e responda às seguintes perguntas:

  1. Qual a média da distribuição?
  2. Qual a mediana da distribuição?
  3. A distribuição possui moda?
  4. Qual o desvio padrão da distribuição?
  5. Qual o coeficiente de variação do seu conjunto de dados?
  6. Faça o gráfico de distribuição de frequências.
  7. Qual a forma da curva? (curva em forma de sino, em J, em J invertido, em U, uniforme, bimodal, trimodal, multimodal…)
  8. Analisando os valores das variáveis, que tipo de dado elas podem representar?
  9. Faça o boxplot da sua distribuição.

What did you think of this article?

0%
Gebruikersscore (0)

Share this article!