By Diego Pedro

Todas as técnicas que você precisa saber para realizar uma ótima análise descritiva.

Neste documento utilizaremos duas bibliotecas fundamentais

library(dplyr)
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(ggplot2)

Os dados utilizados serão referentes oriundos alunos da UFCG. Uma linha dos dados é apresentada abaixo.

Matricula Código do Curso Código da Disciplina Código Evasão Nome do Curso
B7350 14102100 1411191 0 CIÊNCIA DA COMPUTAÇÃO - D
Período Nome da Disciplina Créditos Departamento Média Disciplina
2004.2 INTERCONEXÃO DE REDES DE COMPUTADORES 2 UNID. ACAD. DE SISTEMAS E COMPUTAÇÃO 8.50
Situação Centro Campus Creditos do Curso Tipo
Aprovado 14 1 208 Obrigatória

Sobre as variáveis

Código Evasão: O valor será 0 se o aluno não desistiu e 1 se o aluno desistiu. Este último estará presente apenas no período em que o aluno desistiu e não em todos

Créditos: A quantidade de créditos da disciplina cursada

Período Relativo: A contagem de períodos relativo ao período de ingresso. Por exemplo, se o aluno ingressou na faculdade no período 2002.1, porém após cursar 3 períodos ele trancou dois quando este aluno voltar no período 2004.2 o período relativo será 6, apesar de o mesmo ter cursado apenas 3 períodos.

Os dados consistem de 920529 registros/linhas contendo 32342 Matrículas/alunos

registros <- read.csv("~/Documents/R/alunosUFCGAnon.csv")

Introdução: Comandos Úteis

Removendo valores NA da amostra

registro_limpo <- na.omit(registros)

Remover valores repetidos

unique(c(1,3,4,5,3,2,4))
## [1] 1 3 4 5 2

Selecionado grupo de dados em uma tabela

seleciona todos os registros dos alunos de computacao e eletrica que ingressaram na UFCG antes de 2002.1

condicao1 <- registros$Nome_Curso=='CIÊNCIA DA COMPUTAÇÃO - D'
condicao2 <- registros$Nome_Curso=='ENGENHARIA ELÉTRICA'
condicao3 <- registros$Periodo_Ingresso < 2002.1
alunos_veteranos_do_CEEI <- registros[(condicao1 | condicao2) & condicao3,]

Criar vetor de dados

nome_campus <- c("Campina Grande","Cajazeiras","Sousa","Patos","Cuité","Sumé","Pombal")
campus_code <- c(1,2,3,4,5,7,9)

Converter um valor numerico para literal

as.character(campus_code)
## [1] "1" "2" "3" "4" "5" "7" "9"

Converter um valor literal para numerico

as.numeric(as.character(campus_code))
## [1] 1 2 3 4 5 7 9

Selecionar um conjunto de linhas e colunas em um data frame

O codigo abaixo seleciona entre as colunas 6 a 8, e as linhas 3 a 9

registros[,6:8][3:9,]
##   Periodo                        Nome_Disciplina Creditos
## 3  2005.1     TECC(LAB DE SISTEMAS OPERACIONAIS)        2
## 4  2003.2                      LÓGICA MATEMÁTICA        4
## 5  2002.1 ÁLGEBRA VETORIAL E GEOMETRIA ANALÍTICA        4
## 6  2004.1                  REDES DE COMPUTADORES        4
## 7  2005.2  TECC (ARQUITETURA DE SIST. EMBUTIDOS)        2
## 8  2004.2                INFORMÁTICA E SOCIEDADE        2
## 9  2003.2     PARADIGMAS DE LING. DE PROGRAMAÇÃO        2

Outra forma,mais simples, de realizar a mesma seleção

registros[3:9,6:8]
##   Periodo                        Nome_Disciplina Creditos
## 3  2005.1     TECC(LAB DE SISTEMAS OPERACIONAIS)        2
## 4  2003.2                      LÓGICA MATEMÁTICA        4
## 5  2002.1 ÁLGEBRA VETORIAL E GEOMETRIA ANALÍTICA        4
## 6  2004.1                  REDES DE COMPUTADORES        4
## 7  2005.2  TECC (ARQUITETURA DE SIST. EMBUTIDOS)        2
## 8  2004.2                INFORMÁTICA E SOCIEDADE        2
## 9  2003.2     PARADIGMAS DE LING. DE PROGRAMAÇÃO        2

Converter um data frame em uma matrix

Como pode-se perceber abaixo o nome da disciplina foi convertido para um valor numérico. Isso ocorreu porque matrix em R só aceita valores numéricos.

data.matrix(registros[,6:8][3:9,])
##   Periodo Nome_Disciplina Creditos
## 3  2005.1            3042        2
## 4  2003.2            1881        4
## 5  2002.1              67        4
## 6  2004.1            2653        4
## 7  2005.2            3009        2
## 8  2004.2            1512        2
## 9  2003.2            2225        2

A função Table

Técnica 01 : Mudando o nome de variáveis

for (i in 1:7){
  registros$Campus[registros$Campus == campus_code[i]] <- nome_campus[i]
}

No código acima o código do campus é modificado pelos seus respectivos nomes. Em todas as linhas da tabela que for aceita a seguinte condição acima, o valor será modificado. Poderíamos, por exemplo, modificar apenas o nome dos campus nos registros em que o aluno foi aprovado. Neste caso o código seria o seguinte

registros\(Campus[registros\)Campus == campus_code[i] & registros$Situacao==‘Aprovado’] <- campus_labels[i]

Técnica 02 : Agrupamento

Digamos que eu quero saber quantas matrículas são referentes ao curso de ciência da computação.

Uma forma de resolver isso seria primeiramente selecionar todos os registros referentes ao curso de ciencia da computacao

alunos_computacao <- registros[registros$Nome_Curso=='CIÊNCIA DA COMPUTAÇÃO - D',]

Depois todos os alunos matriculados no curso de Ciência da Computação

alunos_computacao_matriculas <- unique(alunos_computacao[,1])

Eu quero a matricula,primeira coluna,não repetida, de todos os alunos de computacao.

E aqui temos o resultado

length(alunos_computacao_matriculas)
## [1] 1296

E se quisermos obter esta informação para todos os cursos? Uma forma de tornar o código mais limpo seria escrever um for do tipo

nomes_cursos <- as.character(unique(registros$Nome_Curso))
numero_alunos <- data.frame(Nome_Curso=c(nomes_cursos[1]),Numero_Alunos=c(length(unique(registros[registros$Nome_Curso==nomes_cursos[1],][,1]))))

for (i in 2:length(nomes_cursos)){
  registro <- data.frame(Nome_Curso=c(nomes_cursos[i]),Numero_Alunos=c(length(unique(registros[registros$Nome_Curso==nomes_cursos[i],][,1]))))
  numero_alunos <- rbind(numero_alunos,registro)
}
head(numero_alunos)
##                  Nome_Curso Numero_Alunos
## 1 CIÊNCIA DA COMPUTAÇÃO - D          1296
## 2          FÍSICA (BAC) - D           253
## 3      MATEMÁTICA (LIC) - D           472
## 4      MATEMÁTICA (BAC) - D            58
## 5      MATEMÁTICA (LIC) - N           433
## 6          METEOROLOGIA - D           340

Bom, resolveria o problema, mas e se quiséssemos incluir outras informações como Campus e Centro? Isso seria mais complicado e demandaria bastante tempo. E se podermos fazer tudo isso em uma linha e de forma legível? Bom, para isso existe a biblioteca dplyr que fornece a função summarise e group_by

summarise(group_by(registros,Campus,Centro,Nome_Curso),Numero_alunos=length(unique(Matricula)))
## Source: local data frame [95 x 4]
## Groups: Campus, Centro [?]
## 
##        Campus Centro                           Nome_Curso Numero_alunos
##         (chr)  (int)                               (fctr)         (int)
## 1  Cajazeiras     21        CIÊNCIAS BIOLÓGICAS (LIC) - M           151
## 2  Cajazeiras     21                       ENFERMAGEM - D           608
## 3  Cajazeiras     21                     FÍSICA (LIC) - N           143
## 4  Cajazeiras     21         GEOGRAFIA (LICENCIATURA) - M           427
## 5  Cajazeiras     21         GEOGRAFIA (LICENCIATURA) - N           438
## 6  Cajazeiras     21                   HISTÓRIA (LIC) - M           545
## 7  Cajazeiras     21                   HISTÓRIA (LIC) - N           478
## 8  Cajazeiras     21    LETRAS - LÍNGUA INGLESA (LIC) - D            96
## 9  Cajazeiras     21 LETRAS - LÍNGUA PORTUGUESA (LIC) - M            94
## 10 Cajazeiras     21 LETRAS - LÍNGUA PORTUGUESA (LIC) - N           112
## ..        ...    ...                                  ...           ...

No código acima, agrupamos os campos Centro,Campus,Creditos do Curso e Nome do Curso do dataset registros e depois contamos o numero de matriculas não repetidas para cada curso.

Esta função permite summarizações bem interessantes, por exemplo. Eu quero selecionar todos os alunos que chegaram pelo menos no terceiro período

Primeiro eu conto o número de períodos cursados para cada matrícula

numero_alunos <- summarise(group_by(registros,Matricula),Periodos_cursados=length(unique(Periodo)))

Depois eu seleciono apenas as matriculas que cursaram pelo menos o terceiro período

numero_alunos_3 <- numero_alunos[numero_alunos$Periodos_cursados>=3,]

E se eu quiser selecionar apenas os alunos que cursaram pelo menos 5 disciplinas em algum periodo e que a media foi superior ou igual a 7

numero_alunos <- summarise(group_by(registros,Matricula,Periodo),Numero_Disciplinas=n(),Media_Periodo=mean(Media_Disciplina))
numero_alunos <- na.omit(numero_alunos[numero_alunos$Numero_Disciplinas >= 5 & numero_alunos$Media_Periodo >= 7,])

Uma outra forma de agrupar dados é utilizando a função aggregate

No código abaixo é calculado a média de todos os alunos por período de ingresso.

registros <- na.omit(registros)
taxa_desitencia_ingresso <- aggregate(list("Media"=registros$Media_Disciplina),list("Periodo_Ingresso"=registros$Periodo_Ingresso),FUN=mean)
head(taxa_desitencia_ingresso)
##   Periodo_Ingresso     Media
## 1           1995.2 0.9545455
## 2           1996.1 1.1375000
## 3           1997.1 4.9818182
## 4           1997.2 5.6426087
## 5           1998.1 1.5900000
## 6           1998.2 3.9875000

Técnica 03 : Verificar se um item ou conjunto de items contém em um vetor.

Dado o conjunto Q que contém números inteiros quaisquer queremos verificar destes números quais são primos dado um conjunto P que contém apenas números primos.

numeros_primos <- c(2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97)
numeros_qualquer <- c(1,2,3,4,5,6,7)
is.element(numeros_qualquer,numeros_primos)
## [1] FALSE  TRUE  TRUE FALSE  TRUE FALSE  TRUE

Como podemos perceber a funcao is.element retorna valores boleano então isso nos permite fazer uma consulta para saber quais alunos cursaram pelo menos uma disciplina do primeiro período em períodos seguintes. Primeiro precisamos selecionar as disciplinas que são usualmente cursadas no primeiro período

alunos_computacao <- registros[alunos_computacao$Nome_Curso=='CIÊNCIA DA COMPUTAÇÃO - D',]
condicao1 <- alunos_computacao$Periodo_Ingresso==alunos_computacao$Periodo
cursadas_primeiro_periodo <- alunos_computacao[condicao1,]
mais_cursadas <- summarise(group_by(cursadas_primeiro_periodo,Nome_Disciplina),Matriculas=n())

Por fim eu suponho que se o número de matrículas é maior do que a média então tal disciplina é usualmente ministrada para os alunos do primeiro período.

disciplinas_primeiro_periodo <- mais_cursadas[mais_cursadas$Matriculas > mean(mais_cursadas$Matriculas),]$Nome_Disciplina

Agora selecionados os alunos que cursaram disciplinas do primeiro período em períodos posteriores

atrasados <- alunos_computacao[is.element(alunos_computacao$Nome_Disciplina,disciplinas_primeiro_periodo) & alunos_computacao$Periodo != alunos_computacao$Periodo_Ingresso,]

Técnica 04 : Utilizando funções não nativas

Voltando para a técnica 04 onde vimos a função aggregate. Naquele código foi passado como parametro a função para calcular a média. E se quisermos escrever nossa própria função para passar por parâmetro como fazemos?

Por exemplo, para calcular a taxa de desistência por período de ingresso devemos saber a taxa de desistêntes e para isso precisamos utilizar uma função nativa.

Primeiramente precisamos sumarizar os dados apenas para aluno.

alunos <- summarise(group_by(registros,Matricula,Nome_Curso,Creditos_Curso,
                             Periodo_Ingresso,Campus,Centro),
                    Desistiu=sum(Cod_Evasao)>1)

Escrevemos uma função

taxa_desistencia <- function(desistiu){
  s <- data.frame(table(desistiu))
  
  return(s[s$desistiu==TRUE,]$Freq/sum(s$Freq))
}

E usamos esta função

taxa_desitencia_ingresso <- aggregate(list("Taxa"=alunos$Desistiu),list("Periodo_Ingresso"=alunos$Periodo_Ingresso),FUN=taxa_desistencia)
head(taxa_desitencia_ingresso)
##   Periodo_Ingresso Taxa
## 1           1995.2    1
## 2           1996.1     
## 3           1997.1     
## 4           1997.2     
## 5           1998.1 0.75
## 6           1998.2    1

Técnica 05 : Derivando Colunas

Peguemos os eguinte exemplo

N1 <- runif(10, 0.0, 10.0)
N2 <- runif(10, 0.0, 10.0)
N3 <- runif(10, 0.0, 10.0)
notas <- data.frame(N1,N2,N3)
notas
##           N1        N2       N3
## 1  0.1762897 8.6818665 3.333431
## 2  9.9638729 7.9017237 3.663927
## 3  5.1559253 9.1344338 6.807729
## 4  0.3696251 6.7899206 5.603167
## 5  5.5847171 5.8277289 8.252663
## 6  8.9136775 0.6570879 5.462233
## 7  3.4484999 6.6871212 8.420161
## 8  7.7002090 7.7579201 5.767527
## 9  0.4091961 4.8257478 5.010326
## 10 2.1997747 8.4755991 7.588499

Queremos calcular a média, nota final e média final. Para isso precisamos adicionar algumas colunas adicionais.

Primeiro adicionamos a média. Podemos escrever da forma tradicional

notas$media <- (notas$N1+notas$N2+notas$N3)/3

Ou podemos utilizar a função transform

notas <- transform(notas,media=(N1+N2+N3)/3)

Agora calculemos a nota final, apenas para quem foi para a final

notas$final[notas$media >= 5.0 & notas$media < 7] <- runif(2, 0.0, 10.0)

E por fim a média final

notas$media_final <- notas$media
notas$media_final[notas$media >= 5 & notas$media < 7] <- notas$media[notas$media >= 5 & notas$media < 7]*0.6 + notas$final[!is.na(notas$final)]*.4

E se quisermos saber quem foi aprovado criamos outra coluna

notas <- transform(notas,Aprovado=media_final >= 5)

No final temos isso

notas
##           N1        N2       N3    media    final media_final Aprovado
## 1  0.1762897 8.6818665 3.333431 4.063862       NA    4.063862    FALSE
## 2  9.9638729 7.9017237 3.663927 7.176508       NA    7.176508     TRUE
## 3  5.1559253 9.1344338 6.807729 7.032696       NA    7.032696     TRUE
## 4  0.3696251 6.7899206 5.603167 4.254238       NA    4.254238    FALSE
## 5  5.5847171 5.8277289 8.252663 6.555036 9.230279    7.625133     TRUE
## 6  8.9136775 0.6570879 5.462233 5.011000 4.724059    4.896223    FALSE
## 7  3.4484999 6.6871212 8.420161 6.185261 9.230279    7.403268     TRUE
## 8  7.7002090 7.7579201 5.767527 7.075219       NA    7.075219     TRUE
## 9  0.4091961 4.8257478 5.010326 3.415090       NA    3.415090    FALSE
## 10 2.1997747 8.4755991 7.588499 6.087958 4.724059    5.542398     TRUE

Exploração de Dados

Técnica 06 :Plotando várias distribuições no mesmo gráfico

library(gridExtra)
programacao <- alunos_computacao[alunos_computacao$Nome_Disciplina=='PROGRAMAÇÃO I',]
calculo <- alunos_computacao[alunos_computacao$Nome_Disciplina=='CALCULO DIFERENCIAL E INTEGRAL I',]
vetorial <- alunos_computacao[alunos_computacao$Nome_Disciplina=='ÁLGEBRA VETORIAL E GEOMETRIA ANALÍTICA',]

g1 <-ggplot(programacao, aes(Media_Disciplina)) + geom_density() + labs(title = "Notas Programacao")
g2 <-ggplot(calculo, aes(Media_Disciplina)) + geom_density(colour="darkgreen", size=2, fill=NA) + labs(title = "Notas Calculo")
g3 <-ggplot(vetorial, aes(Media_Disciplina)) + geom_density(colour="darkgreen", size=4, fill="orange") + labs(title = "Notas Vetorial")
grid.arrange(g1, g2, g3, nrow=1)

programacao_medias <- select(programacao,Nome_Disciplina,Media_Disciplina)
calculo_medias <- select(calculo,Nome_Disciplina,Media_Disciplina)
vetorial_medias <- select(vetorial,Nome_Disciplina,Media_Disciplina)
dados_plot <- data.frame(programacao_medias[1:1500,2],calculo_medias[1:1500,2],vetorial_medias[1:1500,2])
colnames(dados_plot) <- c('Programacao','Calculo','Vetorial')
dfs <- stack(dados_plot)
ggplot(dfs, aes(x=values)) + geom_density(aes(group=ind, colour=ind, fill=ind), alpha=0.3)

Técnica 07: Plot correlação de dados (intersect de disciplinas, correlacao entre notas)

https://cran.r-project.org/web/packages/corrplot/vignettes/corrplot-intro.html ### Técnica 08: use melt reshape2 df <- melt(forestfires) ggplot(df,aes(x = value)) + facetwrap(~variable, scales = “free_x”) + geom_histogram()

Treinando os dados baixe o arquivo = capes.txt sumarizar por universiade, numero de progrmaas, quantidade de notas de 1 a 7, media rankear

Note that the echo = FALSE parameter was added to the code chunk to prevent printing of the R code that generated the plot.

codigo