O presente notebook, objetiva a utilização das linguagens R e Python (concomitantemente) de forma a realizar análises estatisticas e comparar a utilizaçao de ambas as linguagens.
dados utilizados: PNAD 2015.
Sobre os variáveis:
RENDA: Rendimento mensal do trabalho principal para pessoas de 10 anos ou mais de idade
IDADE: Idade do morador na data de referência em anos
ALTURA: Altura do morador em metros.
UF:
| CODIGO | UF |
|---|---|
| 11 | Rondonia |
| 12 | Acre |
| 13 | Amazonas |
| 14 | Roraima |
| 15 | Para |
| 16 | Amapa |
| 17 | Tocantins |
| 21 | Maranhao |
| 22 | Piaui |
| 23 | Ceara |
| 24 | Rio Grande do Norte |
| 25 | Paraiba |
| 26 | Pernambuco |
| 27 | Alagoas |
| 28 | Sergipe |
| 29 | Bahia |
| 31 | Minas Gerais |
| 32 | Espirito Santo |
| 33 | Rio de Janeiro |
| 35 | Sao Paulo |
| 41 | Parana |
| 42 | Santa Catarina |
| 43 | Rio Grande do Sul |
| 50 | Mato Grosso do Sul |
| 51 | Mato Grosso |
| 52 | Goias |
| 53 | Distrito Federal |
| Nao aplicavel |
Sexo: 0 = Masculino; 1= Feminino
Anos de Estudo:
| CODIGO | DESCRICAO |
|---|---|
| 1 | Sem instrucao e menos de 1 ano |
| 2 | 1 ano |
| 3 | 2 anos |
| 4 | 3 anos |
| 5 | 4 anos |
| 6 | 5 anos |
| 7 | 6 anos |
| 8 | 7 anos |
| 9 | 8 anos |
| 10 | 9 anos |
| 11 | 10 anos |
| 12 | 11 anos |
| 13 | 12 anos |
| 14 | 13 anos |
| 15 | 14 anos |
| 16 | 15 anos ou mais |
| 17 | Não determinado |
| Não aplicável |
Cor:
| CODIGO | DESCRICAO |
|---|---|
| 0 | Indigena |
| 2 | Branca |
| 4 | Preta |
| 6 | Amarela |
| 8 | Parda |
| 9 | Sem declaração |
Informações adicionais:
## Python
import pandas as pd
import numpy as np
import seaborn as sns
import scipy
import matplotlib.pyplot as plt
## R
library(tidyverse)
library(reticulate)
Como serão utilizadas ambas as linguagens, se faz necessário o carregamento de pacotes em chunks diferentes.
## Python
pnad=pd.read_csv("E:\\sandro\\cursos\\formacao_data_science\\estats_medidas_e_frequencias\\datasets\\dados.csv")
## R
pnad=py$pnad
Como replicaremos o processo de análise e trasformação em ambas as linguagens, carregamos o pacote reticulate e em seguida atribuimos ao R o nome de mesmo objeto utilizado em python.
## Python
pnad.head(5)
## UF Sexo Idade Cor Anos de Estudo Renda Altura
## 0 11 0 23 8 12 800 1.603808
## 1 11 1 23 2 12 1150 1.739790
## 2 11 1 35 8 15 880 1.760444
## 3 11 0 46 2 6 3500 1.783158
## 4 11 1 47 8 9 150 1.690631
## R
pnad |> head(5)
## UF Sexo Idade Cor Anos de Estudo Renda Altura
## 1 11 0 23 8 12 800 1.603808
## 2 11 1 23 2 12 1150 1.739790
## 3 11 1 35 8 15 880 1.760444
## 4 11 0 46 2 6 3500 1.783158
## 5 11 1 47 8 9 150 1.690631
De cara ja é possível identificar alguns problemas. Há clara despadronização nas variáveis, uma delas está em maiúsculo e as outras não. além de que, há espaço entre palavras na váriavel ‘Anos de Estudo’ é uma boa prática utilizarmos underline para evitar conflito futuro entre as linguagens.
## Python
# Transforma variáveis em maiusculo
pnad.columns=pnad.columns.str.upper()
# Renomeia variaveis
pnad.rename(columns={'ANOS DE ESTUDO':'ANOS_ESTUDO'}, inplace=True)
# visualiza primeiras linhas
pnad.head(5)
## UF SEXO IDADE COR ANOS_ESTUDO RENDA ALTURA
## 0 11 0 23 8 12 800 1.603808
## 1 11 1 23 2 12 1150 1.739790
## 2 11 1 35 8 15 880 1.760444
## 3 11 0 46 2 6 3500 1.783158
## 4 11 1 47 8 9 150 1.690631
## R
# Transforma variáveis em maiúsculo
names(pnad) <- toupper(names(pnad))
# Renomeia variáveis
colnames(pnad)[5] <- 'ANOS_ESTUDO'
# visualiza primeiras linhas
head(pnad,5)
## UF SEXO IDADE COR ANOS_ESTUDO RENDA ALTURA
## 1 11 0 23 8 12 800 1.603808
## 2 11 1 23 2 12 1150 1.739790
## 3 11 1 35 8 15 880 1.760444
## 4 11 0 46 2 6 3500 1.783158
## 5 11 1 47 8 9 150 1.690631
## Python
pnad.isnull().sum().tolist
## <bound method IndexOpsMixin.tolist of UF 0
## SEXO 0
## IDADE 0
## COR 0
## ANOS_ESTUDO 0
## RENDA 0
## ALTURA 0
## dtype: int64>
## R
as.data.frame(colSums(is.na(pnad)))
## colSums(is.na(pnad))
## UF 0
## SEXO 0
## IDADE 0
## COR 0
## ANOS_ESTUDO 0
## RENDA 0
## ALTURA 0
Não valores faltantes no dataset.
## Python
pnad.info()
## <class 'pandas.core.frame.DataFrame'>
## RangeIndex: 76840 entries, 0 to 76839
## Data columns (total 7 columns):
## # Column Non-Null Count Dtype
## --- ------ -------------- -----
## 0 UF 76840 non-null int64
## 1 SEXO 76840 non-null int64
## 2 IDADE 76840 non-null int64
## 3 COR 76840 non-null int64
## 4 ANOS_ESTUDO 76840 non-null int64
## 5 RENDA 76840 non-null int64
## 6 ALTURA 76840 non-null float64
## dtypes: float64(1), int64(6)
## memory usage: 4.1 MB
## R
pnad |> glimpse()
## Rows: 76,840
## Columns: 7
## $ UF <dbl> 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11~
## $ SEXO <dbl> 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1~
## $ IDADE <dbl> 23, 23, 35, 46, 47, 34, 57, 60, 50, 26, 46, 49, 52, 38, 45~
## $ COR <dbl> 8, 2, 8, 2, 8, 8, 8, 8, 4, 8, 8, 8, 2, 8, 2, 2, 8, 8, 2, 8~
## $ ANOS_ESTUDO <dbl> 12, 12, 15, 6, 9, 12, 12, 12, 14, 12, 12, 6, 6, 12, 12, 16~
## $ RENDA <dbl> 800, 1150, 880, 3500, 150, 790, 3150, 1700, 1800, 1150, 30~
## $ ALTURA <dbl> 1.603808, 1.739790, 1.760444, 1.783158, 1.690631, 1.637906~
Apesar de todas as variáveis estarem como no tipo numérica, algumas delas tratam-se de variáveis do tipo Qualitativas Nominais.
Abaixo um breve demonstrativo sobre tipos de variáveis:
## Python
# altera tipagem de variáveis
pnad['UF']=pnad['UF'].astype(int).astype(str)
pnad['SEXO']=pnad['SEXO'].astype(int).astype(str)
pnad['COR']=pnad['COR'].astype(int).astype(str)
pnad['ANOS_ESTUDO']=pnad['ANOS_ESTUDO'].astype(int).astype(str)
## R
# altera tipagem de variaveis
df_tip <- pnad |>
select(UF,SEXO,COR, ANOS_ESTUDO) |>
mutate_if(is.numeric,as.character)
pnad <- pnad |>
select(-UF,-SEXO,-COR,-ANOS_ESTUDO) |>
cbind(df_tip) |>
select(UF,SEXO,IDADE,COR,ANOS_ESTUDO,RENDA,ALTURA)
rm(df_tip)
## Python
sorted(pnad['UF'].unique())
## ['11', '12', '13', '14', '15', '16', '17', '21', '22', '23', '24', '25', '26', '27', '28', '29', '31', '32', '33', '35', '41', '42', '43', '50', '51', '52', '53']
## R
pnad |> select(UF) |> unique() |> arrange(UF) |> as.list()
## $UF
## [1] "11" "12" "13" "14" "15" "16" "17" "21" "22" "23" "24" "25" "26" "27" "28"
## [16] "29" "31" "32" "33" "35" "41" "42" "43" "50" "51" "52" "53"
## Python
pnad['COR'].value_counts()
## 8 35925
## 2 31815
## 4 8391
## 0 357
## 6 352
## Name: COR, dtype: int64
## R
pnad |> group_by(COR) |> dplyr::summarise(n=n()) |> arrange(desc(n))
## # A tibble: 5 x 2
## COR n
## <chr> <int>
## 1 8 35925
## 2 2 31815
## 3 4 8391
## 4 0 357
## 5 6 352
## Python
pnad['COR'].value_counts(normalize=True)
## 8 0.467530
## 2 0.414042
## 4 0.109201
## 0 0.004646
## 6 0.004581
## Name: COR, dtype: float64
## R
pnad |> group_by(COR) |> dplyr::summarise(n=n()) |> mutate(percent=n/sum(n)) |> select(-n) |> arrange(desc(percent))
## # A tibble: 5 x 2
## COR percent
## <chr> <dbl>
## 1 8 0.468
## 2 2 0.414
## 3 4 0.109
## 4 0 0.00465
## 5 6 0.00458
## Python
# serie de percentuais por sexo
percent=pnad['SEXO'].value_counts(normalize=True)
# serie de frequencia por sexo
freq=pnad['SEXO'].value_counts()
# dataframe com agregacao de frequencia e percentual
dist=pd.DataFrame({'FREQ':freq,'PERCENT':percent})
# substitui valores do index
dist.rename(index={0:'M',1:'F'},inplace=True)
# transforma o index em coluna
dist=dist.rename_axis('SEXO').reset_index()
dist
## SEXO FREQ PERCENT
## 0 0 53250 0.692998
## 1 1 23590 0.307002
## R
pnad |>
group_by(SEXO) |>
dplyr::summarise(FREQ = n()) |>
mutate(PER = FREQ / sum(FREQ),
SEXO = plyr::mapvalues(SEXO,
from =c(0, 1),
to =c('M', 'F')))
## # A tibble: 2 x 3
## SEXO FREQ PER
## <chr> <int> <dbl>
## 1 M 53250 0.693
## 2 F 23590 0.307
## Python
sexo={'0':'M',1:'F'}
cor={'0': 'Indígena',
'2': 'Branca',
'4': 'Preta',
'6': 'Amarela',
'8': 'Parda',
'9': 'Sem declaração'}
percent=pd.crosstab(pnad['SEXO'],pnad['COR'],normalize=True)
percent.rename(index=sexo,inplace=True)
percent.rename(columns=cor,inplace=True)
percent
## COR Indígena Branca Preta Amarela Parda
## SEXO
## M 0.003332 0.288834 0.071603 0.003058 0.326171
## 1 0.001314 0.125208 0.037598 0.001523 0.141359
## R
pnad |>
group_by(SEXO,COR) |>
dplyr::summarise(n=n()) |>
as.data.frame() |>
mutate(n2=sum(n),
FREQ=n/n2) |>
select(-n2,-n) |>
mutate(COR = plyr::mapvalues(COR,
from = c(0,2,4,6,8,9),
to = c('indigena','branca','preta','amarela','parda','sem decl.')),
SEXO = plyr::mapvalues(SEXO,
from=c(0,1),
to=c('M','F'))) |>
mutate_if(is.character,toupper) |>
pivot_wider(names_from=COR,values_from=FREQ)
## # A tibble: 2 x 6
## SEXO INDIGENA BRANCA PRETA AMARELA PARDA
## <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 M 0.00333 0.289 0.0716 0.00306 0.326
## 2 F 0.00131 0.125 0.0376 0.00152 0.141
## Python
renda_media=pd.crosstab(pnad['SEXO'],
pnad['COR'],aggfunc='mean',values=pnad['RENDA'])
renda_media.rename(index=sexo,inplace=True)
renda_media.rename(columns=cor,inplace=True);renda_media
## COR Indígena Branca Preta Amarela Parda
## SEXO
## M 1081.710938 2925.744435 1603.861687 4758.251064 1659.577425
## 1 2464.386139 2109.866750 1134.596400 3027.341880 1176.758516
## R
pnad |> group_by(SEXO,COR) |>
summarise(RENDA_MEDIA = mean(RENDA)) |>
mutate(COR = plyr::mapvalues(COR,
from = c(0,2,4,6,8,9),
to = c('indigena','branca','preta','amarela','parda','sem decl.')),
SEXO = plyr::mapvalues(SEXO,
from=c(0,1),
to=c('M','F'))) |>
mutate_if(is.character,toupper) |>
pivot_wider(values_from=RENDA_MEDIA,names_from=COR)
## # A tibble: 2 x 6
## # Groups: SEXO [2]
## SEXO INDIGENA BRANCA PRETA AMARELA PARDA
## <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 M 1082. 2926. 1604. 4758. 1660.
## 2 F 2464. 2110. 1135. 3027. 1177.
## Python
# verficando valores máx e min de salário
print('o valor minimo de salario é:', pnad['RENDA'].min())
## o valor minimo de salario é: 0
print('o valor maximo de salario é:',pnad['RENDA'].max())
## o valor maximo de salario é: 200000
## R
options(scipen = 99999)
# verificando valores máx e min de salário
range(pnad |> select(RENDA))
## [1] 0 200000
# limites de classes
classes = [0, 1576, 3152, 7880, 15760, 200000]
# labels
labels = ['E', 'D', 'C', 'B', 'A']
## Python
# cria percentual
percentual=pd.value_counts(pd.cut(x=pnad['RENDA'],bins=classes,labels=labels,include_lowest=True),
normalize=True)
# cria frequencia
frequencia=pd.value_counts(pd.cut(x=pnad['RENDA'],bins=classes,labels=labels,include_lowest=True))
# agrega frequencia e percentual em um dataframe
dist=pd.DataFrame({'FREQ':frequencia,'PERCENT':percentual})
# transforma o index em coluna
dist.sort_index(ascending=False,inplace=True)
dist=dist.rename_axis('CLASS').reset_index()
dist
## CLASS FREQ PERCENT
## 0 A 608 0.007913
## 1 B 2178 0.028345
## 2 C 7599 0.098894
## 3 D 16700 0.217335
## 4 E 49755 0.647514
## R
# cria classes
dist=pnad |>
mutate(CLASS=ifelse(RENDA <=1576,'e',
ifelse(RENDA >1576 & RENDA <= 3152,'d',
ifelse(RENDA >3152 & RENDA <=7880,'c',
ifelse(RENDA>7880 & RENDA <= 15760,'b',
ifelse(RENDA >15760,'a','x')))))) |>
select(CLASS,RENDA) |>
group_by(CLASS) |>
dplyr::summarise(FREQ=n()) |>
mutate(PERCENT=FREQ/sum(FREQ)) |>
mutate_if(is.character,toupper)
dist |> head()
## # A tibble: 5 x 3
## CLASS FREQ PERCENT
## <chr> <int> <dbl>
## 1 A 608 0.00791
## 2 B 2178 0.0283
## 3 C 7599 0.0989
## 4 D 16700 0.217
## 5 E 49755 0.648
Também é possível realizar essa classificação utilizando o regra de Sturges.
A Regra de Sturges é uma função linear em escala logarítmica, onde o máximo para 100.000 pontos de dados são 18 classes.
k=1+(10/3 log10 N)
# define o valor de n a partir do tamanho dos dados
n=pnad.shape[0];n
## 76840
# aplica a funcao de sturges e define o valor de k
k=1+(10/3)*np.log10(n)
k=int(round(k));k
## 17
# cria frequencia a partir do valor de k
frequencia=pd.value_counts(pd.cut(x=pnad['RENDA'],bins=k,include_lowest=True),sort=False)
# cria o percentual a partir do valor de k
percentual=pd.value_counts(pd.cut(x=pnad['RENDA'],bins=k,include_lowest=True),normalize=True,sort=False)
# cria agregacao com dataframe entre percetual e frequencia
dist2=pd.DataFrame({'FREQ':frequencia,'PERCENT':percentual})
# transforma o index em coluna
dist2=dist2.rename_axis('CLASS').reset_index()
dist2
## CLASS FREQ PERCENT
## 0 (-200.001, 11764.706] 75594 0.983784
## 1 (11764.706, 23529.412] 1022 0.013300
## 2 (23529.412, 35294.118] 169 0.002199
## 3 (35294.118, 47058.824] 19 0.000247
## 4 (47058.824, 58823.529] 16 0.000208
## 5 (58823.529, 70588.235] 5 0.000065
## 6 (70588.235, 82352.941] 4 0.000052
## 7 (82352.941, 94117.647] 1 0.000013
## 8 (94117.647, 105882.353] 6 0.000078
## 9 (105882.353, 117647.059] 0 0.000000
## 10 (117647.059, 129411.765] 1 0.000013
## 11 (129411.765, 141176.471] 0 0.000000
## 12 (141176.471, 152941.176] 0 0.000000
## 13 (152941.176, 164705.882] 0 0.000000
## 14 (164705.882, 176470.588] 0 0.000000
## 15 (176470.588, 188235.294] 0 0.000000
## 16 (188235.294, 200000.0] 3 0.000039
plt.close()
ax = sns.distplot(pnad.ALTURA, kde = False,color='blue')
## <string>:1: UserWarning:
##
## `distplot` is a deprecated function and will be removed in seaborn v0.14.0.
##
## Please adapt your code to use either `displot` (a figure-level function with
## similar flexibility) or `histplot` (an axes-level function for histograms).
##
## For a guide to updating your code to use the new functions, please see
## https://gist.github.com/mwaskom/de44147ed2974457ad6372750bbe5751
ax.figure.set_size_inches(12, 6)
ax.set_title('Distribuição de Frequências - Altura', fontsize=18)
ax.set_xlabel('Metros', fontsize=12)
ax.set_ylabel('Freq',fontsize=12)
plt.show()
plt.close()
ax=sns.barplot(data=dist,x='CLASS',y='FREQ')
ax.set_title('Frequency by class')
plt.show()
# criando dataframe
df = pd.DataFrame(data = {'Fulano': [8, 10, 4, 8, 6, 10, 8],
'Beltrano': [10, 2, 0.5, 1, 3, 9.5, 10],
'Sicrano': [7.5, 8, 7, 8, 8, 8.5, 7]},
index = ['Matematica',
'Portugues',
'Ingles',
'Geografia',
'Histeria',
'Fisica',
'Quimica'])
df=df.rename_axis('Disciplina').reset_index()
df
## Disciplina Fulano Beltrano Sicrano
## 0 Matematica 8 10.0 7.5
## 1 Portugues 10 2.0 8.0
## 2 Ingles 4 0.5 7.0
## 3 Geografia 8 1.0 8.0
## 4 Histeria 6 3.0 8.0
## 5 Fisica 10 9.5 8.5
## 6 Quimica 8 10.0 7.0
# calculando somente a media de fulano
df['Fulano'].mean()
## 7.714285714285714
# calculando a renda media por sexo
pnad.groupby(['SEXO'])['RENDA'].mean()
## SEXO
## 0 2192.441596
## 1 1566.847393
## Name: RENDA, dtype: float64
# exercicio - localizando media dos homens
dataset = pd.DataFrame({
'Sexo': ['H', 'M', 'M', 'M', 'M', 'H', 'H', 'H', 'M', 'M'],
'Idade': [53, 72, 54, 27, 30, 40, 58, 32, 44, 51]
})
dataset.groupby(['Sexo'])['Idade'].mean().loc['H']
## 45.75
# realizando o pivot longer no dataset
df=pd.melt(df,id_vars='Disciplina',value_vars=['Fulano','Beltrano','Sicrano'])
# trasforma as varieveis em maiusculo
df.columns=df.columns.str.upper()
# renomeia variaveis
df.rename(columns={'VARIABLE':'ALUNO','VALUE':'NOTA'},inplace=True)
df
## DISCIPLINA ALUNO NOTA
## 0 Matematica Fulano 8.0
## 1 Portugues Fulano 10.0
## 2 Ingles Fulano 4.0
## 3 Geografia Fulano 8.0
## 4 Histeria Fulano 6.0
## 5 Fisica Fulano 10.0
## 6 Quimica Fulano 8.0
## 7 Matematica Beltrano 10.0
## 8 Portugues Beltrano 2.0
## 9 Ingles Beltrano 0.5
## 10 Geografia Beltrano 1.0
## 11 Histeria Beltrano 3.0
## 12 Fisica Beltrano 9.5
## 13 Quimica Beltrano 10.0
## 14 Matematica Sicrano 7.5
## 15 Portugues Sicrano 8.0
## 16 Ingles Sicrano 7.0
## 17 Geografia Sicrano 8.0
## 18 Histeria Sicrano 8.0
## 19 Fisica Sicrano 8.5
## 20 Quimica Sicrano 7.0
# calculando a media por disciplina
df.groupby(['DISCIPLINA'])['NOTA'].mean()
## DISCIPLINA
## Fisica 9.333333
## Geografia 5.666667
## Histeria 5.666667
## Ingles 3.833333
## Matematica 8.500000
## Portugues 6.666667
## Quimica 8.333333
## Name: NOTA, dtype: float64
# calculando a nota media de Fulano
df.groupby(['ALUNO'])['NOTA'].mean().loc['Fulano']
## 7.714285714285714
# Calculando a nota media de Fulano por disciplina
df[df.ALUNO == 'Fulano'].groupby(['DISCIPLINA'])['NOTA'].mean()
## DISCIPLINA
## Fisica 10.0
## Geografia 8.0
## Histeria 6.0
## Ingles 4.0
## Matematica 8.0
## Portugues 10.0
## Quimica 8.0
## Name: NOTA, dtype: float64
# seleciona notas do fulano
notas_fulano=df[df.ALUNO=='Fulano'][['DISCIPLINA','NOTA']]
# organiza os valores de nota por ordem crescente
notas_fulano.sort_values(by='NOTA',ascending=True,inplace=True)
# reseta o index
notas_fulano.reset_index(inplace=True)
# elimina o index antigo do dataset
notas_fulano[['DISCIPLINA','NOTA']]
## DISCIPLINA NOTA
## 0 Ingles 4.0
## 1 Histeria 6.0
## 2 Matematica 8.0
## 3 Geografia 8.0
## 4 Quimica 8.0
## 5 Portugues 10.0
## 6 Fisica 10.0
# calcula o valor mediano de notas de fulano
notas_fulano['NOTA'].median()
## 8.0
# calcula o valor de nota mediana da disciplina Ingles
df[df.DISCIPLINA=='Ingles'][['NOTA']].median()
## NOTA 4.0
## dtype: float64
# selecionando amostra aleatoria
notas_beltrano=df[df.ALUNO == 'Beltrano'][['DISCIPLINA','NOTA']].sample(4, random_state=123)
# calculando mediana a partir da amostra aleatoria de beltrano
notas_beltrano['NOTA'].median()
## 2.5
# calculando mediana de renda por sexo
pnad.groupby(['SEXO'])['RENDA'].median()
## SEXO
## 0 1350.0
## 1 900.0
## Name: RENDA, dtype: float64
# plotando o valor que mais se repete na variavel NOTA
df[['NOTA']].mode()
## NOTA
## 0 8.0
# valor que mais se repete na disciplina geografia
df[df['DISCIPLINA'] == 'Geografia']['NOTA'].mode()
## 0 8.0
## Name: NOTA, dtype: float64
# moda de idade da base do pnad
pnad['IDADE'].mode()
## 0 40
## Name: IDADE, dtype: int64
plt.close()
ax=sns.distplot(pnad.query('RENDA < 20000').RENDA)
## <string>:1: UserWarning:
##
## `distplot` is a deprecated function and will be removed in seaborn v0.14.0.
##
## Please adapt your code to use either `displot` (a figure-level function with
## similar flexibility) or `histplot` (an axes-level function for histograms).
##
## For a guide to updating your code to use the new functions, please see
## https://gist.github.com/mwaskom/de44147ed2974457ad6372750bbe5751
ax.figure.set_size_inches(12,6)
ax
plt.show()
O plot possui assimetria à direita.
# criando objetos de moda, media e mediana
moda=pnad['RENDA'].mode()[0]
media=pnad['RENDA'].mean()
mediana=pnad['RENDA'].median()
# printa os resultados na tela
print('Moda: ',moda)
## Moda: 788
print('Media: ',media)
## Media: 2000.3831988547631
print('Mediana:',mediana)
## Mediana: 1200.0
# confirmando se o plot é simetrico a direita
moda<mediana<media
## True
Como o resultado é igual a true, de fato há um comportamento de asimetria com cauda a direita
# verificando a distribuiçao de altura
plt.close()
ax=sns.displot(pnad.ALTURA)
ax.figure.set_size_inches(12,6)
ax
plt.show()
# calculando medida
moda=pnad.ALTURA.mode()
media=pnad.ALTURA.mean()
mediana=pnad.ALTURA.median()
# printa os resultados na tela
print('Moda: ', moda)
## Moda: 0 1.568128
## 1 1.671225
## 2 1.681659
## 3 1.692977
## 4 1.708163
## 5 1.708370
## 6 1.753842
## 7 1.779073
## 8 1.796462
## Name: ALTURA, dtype: float64
print('Media: ',media)
## Media: 1.6995124540575741
print('Mediana:',mediana)
## Mediana: 1.6993247325
A serie é multimodal, e mediana e media tem valor muito aproximado à moda. Ou seja é caracteristico de simetria.
# serie de anos de estudo
plt.close()
ax=sns.distplot(pnad.ANOS_ESTUDO)
## <string>:1: UserWarning:
##
## `distplot` is a deprecated function and will be removed in seaborn v0.14.0.
##
## Please adapt your code to use either `displot` (a figure-level function with
## similar flexibility) or `histplot` (an axes-level function for histograms).
##
## For a guide to updating your code to use the new functions, please see
## https://gist.github.com/mwaskom/de44147ed2974457ad6372750bbe5751
ax.figure.set_size_inches(12,6)
plt.show()
A distribuição possui caracteristica de bastante irregularidade com picos e vales bastante acentuados.
Se considerarmos somente os picos, encontraremos um comportamento bastante parecido com o padrao de assimetria a esquerda, pois os mairoes picos aparecem conforme os valores do eixo x sobem.
# moda, media e mediana
pnad['ANOS_ESTUDO']=pnad['ANOS_ESTUDO'].astype(int)
moda=pnad.ANOS_ESTUDO.mode()[0]
media=pnad.ANOS_ESTUDO.mean().round()
mediana=pnad.ANOS_ESTUDO.median()
# print
print('Moda: ',moda)
## Moda: 12
print('Media: ',media)
## Media: 9.0
print('Mediana:',mediana)
## Mediana: 11.0
pnad.info()
## <class 'pandas.core.frame.DataFrame'>
## RangeIndex: 76840 entries, 0 to 76839
## Data columns (total 7 columns):
## # Column Non-Null Count Dtype
## --- ------ -------------- -----
## 0 UF 76840 non-null object
## 1 SEXO 76840 non-null object
## 2 IDADE 76840 non-null int64
## 3 COR 76840 non-null object
## 4 ANOS_ESTUDO 76840 non-null int32
## 5 RENDA 76840 non-null int64
## 6 ALTURA 76840 non-null float64
## dtypes: float64(1), int32(1), int64(2), object(3)
## memory usage: 3.8+ MB
moda>media>mediana
## False
Ou seja, se a moda é MAIOR que a mediana e a mediana é maior que a media, entao trata-se de uma assimetria à esquerda.
Se a moda é MENOR que a mediana e a mediana é maior que a media, entao trata-se de uma assimetria à direita
Quartis: divide a variavel em quatro partes iguais quanto ao numero de elemetos de cada uma;
Decis: divide em dez partes iguais;
Percentis: divide em cem partes iguais.
As medidades separatrizes não sao influenciadas por valores extremos (outliers).
Esses calculos permitem analises importantes a partir de um ponto de referencia, como o salario minimo por exemplo. Tambem poderemos construir classificacoes com essas medidas, como as classes A,B,C,D,e E.
# calculando o quantile = 0.5 (mediana)
pnad['RENDA'].quantile()
## 1200.0
# calculando os quartis
pnad['RENDA'].quantile([0.25,0.5,0.75])
## 0.25 788.0
## 0.50 1200.0
## 0.75 2000.0
## Name: RENDA, dtype: float64
# calculando os decis
pnad['RENDA'].quantile([i/10 for i in range(1,10)])
## 0.1 350.0
## 0.2 788.0
## 0.3 800.0
## 0.4 1000.0
## 0.5 1200.0
## 0.6 1500.0
## 0.7 1900.0
## 0.8 2500.0
## 0.9 4000.0
## Name: RENDA, dtype: float64
# calculando os percentis
pnad['RENDA'].quantile([i/100 for i in range(1,99)])
## 0.01 0.0
## 0.02 0.0
## 0.03 0.0
## 0.04 50.0
## 0.05 100.0
## ...
## 0.94 5400.0
## 0.95 6000.0
## 0.96 7000.0
## 0.97 8000.0
## 0.98 10000.0
## Name: RENDA, Length: 98, dtype: float64
plt.close()
ax = sns.distplot(pnad.IDADE,
hist_kws = {'cumulative': True},
kde_kws = {'cumulative': True})
## <string>:1: UserWarning:
##
## `distplot` is a deprecated function and will be removed in seaborn v0.14.0.
##
## Please adapt your code to use either `displot` (a figure-level function with
## similar flexibility) or `histplot` (an axes-level function for histograms).
##
## For a guide to updating your code to use the new functions, please see
## https://gist.github.com/mwaskom/de44147ed2974457ad6372750bbe5751
ax.figure.set_size_inches(14, 6)
ax.set_title('Distribuição de Frequências Acumulada', fontsize=18)
ax.set_ylabel('Acumulado', fontsize=14)
ax.set_xlabel('Anos', fontsize=14)
ax
plt.show()
# decis de idade
pnad.IDADE.quantile([i / 10 for i in range(1, 10)])
## 0.1 28.0
## 0.2 33.0
## 0.3 36.0
## 0.4 40.0
## 0.5 43.0
## 0.6 47.0
## 0.7 51.0
## 0.8 55.0
## 0.9 61.0
## Name: IDADE, dtype: float64
Com o retorno podemos constatar que, 40% das pessoas entrevistadas possuem até quarenta anos de idade ou que 90% possuem menos de 61 anos
plt.close()
ax = sns.distplot(pnad.IDADE,
hist_kws = {'cumulative': True},
kde_kws = {'cumulative': True},
bins = 10)
## <string>:1: UserWarning:
##
## `distplot` is a deprecated function and will be removed in seaborn v0.14.0.
##
## Please adapt your code to use either `displot` (a figure-level function with
## similar flexibility) or `histplot` (an axes-level function for histograms).
##
## For a guide to updating your code to use the new functions, please see
## https://gist.github.com/mwaskom/de44147ed2974457ad6372750bbe5751
ax.figure.set_size_inches(14, 6)
ax.set_title('Distribuição de Frequências Acumulada', fontsize=18)
ax.set_ylabel('Acumulado', fontsize=14)
ax.set_xlabel('Anos', fontsize=14)
ax
plt.show()

Q1 representa o primeiro quartil de 25%,
Ao meio teremos a mediana
Q3 represente o terceiro quartil
IIQ é o indice interquartil, a diferença entre o Q3 e o Q1
Os extremos da representação gráfica são construídos como Q1 - 1,5 xI IQ e Q3 +1,5 x IIQ
plt.close()
ax = sns.boxplot( x = 'ALTURA', y = 'SEXO', data = pnad, orient = 'h')
ax.figure.set_size_inches(12, 4)
ax.set_title('Altura', fontsize=18)
ax.set_xlabel('Metros', fontsize=14)
ax
plt.show()
Comparando as medidas entre as duas series, nao veremos quase nenhuma diferença entre as variaveis, pois altura foi construida simetricamente.
plt.close()
ax = sns.boxplot( x = 'RENDA', data = pnad, orient = 'h')
ax.figure.set_size_inches(12, 4)
ax.set_title('Renda', fontsize=18)
ax.set_xlabel('R$', fontsize=14)
ax
plt.show()
plt.close()
ax = sns.boxplot( x = 'RENDA', y='SEXO', data = pnad.query('RENDA < 10000'),
orient = 'h')
ax.figure.set_size_inches(12, 4)
ax.set_title('Renda', fontsize=18)
ax.set_xlabel('R$', fontsize=14)
ax
plt.show()
plt.close()
ax = sns.boxplot( x = 'ANOS_ESTUDO', y = 'SEXO', data = pnad, orient = 'h')
ax.figure.set_size_inches(12, 4)
ax.set_title('Anos de Estudo', fontsize=18)
ax.set_xlabel('Anos', fontsize=14)
ax
plt.show()

DM é igual ao somatorio dos desvios formado pelo modulo de X indice i que o valor de cada nota do df menos a media geral X. A ultima parte entre barras significa que somente pegaremos os valores absolutos ou seja, positivos.
Em um caso onde a média é maior do que o valor, como o complemento de X sendo igual a 10 e x no indice i for igual a 2 por exemplo, o resultado final da conta sera -8. Como queremos apenas 8, retiraremos o sinal de subtracao e entenderemos o porque adiante.
Aplicaremos esta estatistica para fulano na celula.
# cria dataframe de notas do fulano
notas_fulano=df[df.ALUNO == 'Fulano'][['DISCIPLINA','NOTA']]
# cria nota_media_fulano
nota_media_fulano=notas_fulano['NOTA'].mean()
# cria variavel de desvio
notas_fulano['DESVIO']=notas_fulano['NOTA']-nota_media_fulano
notas_fulano
## DISCIPLINA NOTA DESVIO
## 0 Matematica 8.0 0.285714
## 1 Portugues 10.0 2.285714
## 2 Ingles 4.0 -3.714286
## 3 Geografia 8.0 0.285714
## 4 Histeria 6.0 -1.714286
## 5 Fisica 10.0 2.285714
## 6 Quimica 8.0 0.285714
# desvio absoluto
notas_fulano['|DESVIO|']=notas_fulano['DESVIO'].abs()
notas_fulano
## DISCIPLINA NOTA DESVIO |DESVIO|
## 0 Matematica 8.0 0.285714 0.285714
## 1 Portugues 10.0 2.285714 2.285714
## 2 Ingles 4.0 -3.714286 3.714286
## 3 Geografia 8.0 0.285714 0.285714
## 4 Histeria 6.0 -1.714286 1.714286
## 5 Fisica 10.0 2.285714 2.285714
## 6 Quimica 8.0 0.285714 0.285714
plt.close()
ax = notas_fulano['NOTA'].plot(style = 'o')
ax.figure.set_size_inches(14, 6)
ax.hlines(y = nota_media_fulano, xmin = 0, xmax = notas_fulano.shape[0] - 1, colors = 'red')
for i in range(notas_fulano.shape[0]):
ax.vlines(x = i, ymin = nota_media_fulano, ymax = notas_fulano['NOTA'][i], linestyle='dashed')
ax
plt.show()
desvio_medio_absoluto = notas_fulano['NOTA'].mad()
desvio_medio_absoluto
## 1.5510204081632648
df = pd.DataFrame(data = {'Fulano': [8, 10, 4, 8, 6, 10, 8],
'Sicrano': [7.5, 8, 7, 8, 8, 8.5, 7]},
index = ['Matemática',
'Português',
'Inglês',
'Geografia',
'História',
'Física',
'Química'])
df.rename_axis('Matérias', axis = 'columns', inplace = True)
df
## Matérias Fulano Sicrano
## Matemática 8 7.5
## Português 10 8.0
## Inglês 4 7.0
## Geografia 8 8.0
## História 6 8.0
## Física 10 8.5
## Química 8 7.0
# dispersao desvio medio absoluto
# nota media fulano e sicrano
nota_media_fulano=df['Fulano'].mean()
nota_media_sicrano=df['Sicrano'].mean()
# datasets
notas_fulano=df[['Fulano']]
notas_sicrano=df[['Sicrano']]
# desvios
notas_fulano['Desvio']=notas_fulano['Fulano']-nota_media_fulano
notas_sicrano['Desvio']=notas_sicrano['Sicrano']-nota_media_sicrano
notas_fulano['|desvio|']=notas_fulano['Desvio'].abs()
notas_sicrano['|desvio|']=notas_sicrano['Desvio'].abs()
# desvio medio absoluto
desvio_fulano=notas_fulano['Desvio'].mad()
desvio_sicrano=notas_sicrano['Desvio'].mad()
# print
print('------ DESVIO MEDIO ABSOLUTO ------')
## ------ DESVIO MEDIO ABSOLUTO ------
print('Fulano: ',desvio_fulano)
## Fulano: 1.551020408163265
print('Sicrano:',desvio_sicrano)
## Sicrano: 0.4693877551020408
É a soma do quadrado dos desvios dividido pelo numero total.
O primeiro calculo é representado por sigma ao quadrado, sendo igual ao somatorio dos desvios em relacao a media populacional representada por mi e dividido por n
Ja no segundo, dividremos por n-1 conhecido como fator de correcao de bessel. Utilizando-o teremos uma estimativa mais precido do parametro populacional.
notas_fulano['(Desvio)^2']=notas_fulano['Desvio'].pow(2)
notas_fulano['(Desvio)^2'].sum() / (len(notas_fulano) - 1)
## 4.57142857142857
variancia = notas_fulano['Fulano'].var()
É a medida de dispersao mais conhecida.
Este calculo é justamente a raiz quadradada da variancia vista no passo anterior, cujo resultado é a media dos desvios ao quadrado.
desvio_padrao=notas_fulano['Fulano'].std()
desvio_padrao
## 2.1380899352993947
df.std()
## Matérias
## Fulano 2.138090
## Sicrano 0.566947
## dtype: float64
Essa estatistica mostra que sicrano possui o desvio padrao menor, ou seja, possui valores mais constantes e proximos, enquanto fulano é mais instável, o que é possivel observa diretamente no boletim de notas.
dataset = pd.DataFrame({
'Sexo': ['H', 'M', 'M', 'M', 'M', 'H', 'H', 'H', 'M', 'M'],
'Idade': [53, 72, 54, 27, 30, 40, 58, 32, 44, 51]
})
m=dataset[dataset.Sexo == 'M']['Idade']
h=dataset[dataset.Sexo=='H']['Idade']
i=dataset['Idade']
print('----- STD -----')
## ----- STD -----
print('h:',h.std())
## h: 11.89887949906769
print('m:',m.std())
## m: 16.64531966249572
print('i:',i.std())
## i: 14.184890239656813