Material adaptado do Apêndice A do livro: “Uma Breve Introdução à Mineração de Dados: Bases Para a Ciência de Dados, com Exemplos em R.” por Joaquim V. C. Assunção.
Contato: joaquim@inf.ufsm.br
Material adaptado do Apêndice A do livro: “Uma Breve Introdução à Mineração de Dados: Bases Para a Ciência de Dados, com Exemplos em R.” por Joaquim V. C. Assunção.
Contato: joaquim@inf.ufsm.br
R é uma variante da linguagem S. Foi criada em 1991 por Ross Ihaka e por Robert Gentleman no departamento de Estatística da universidade de Auckland, Nova Zelândia. Foi desenvolvido em um esforço colaborativo de pessoas em vários locais do mundo. Foi exposta ao público em 93.
Usada principalmente por estatísticos, matemáticos e cientístas de dados. R
Segundo o site www.r-project.org: “R é um conjunto integrado de instalações de software para manipulação de dados, cálculo e exibição gráfica”; que inclui:
Você pode digitar os comandos diretamente no console (janela de comandos), ou criar um script com o código.
Usamos print(<var>)
para imprimir uma variável. Isto é, fazer uma saída na tela correspondente ao valor da variável em questão. No console, a chamada print(<var>)
acontece implicitamente.
> x <- 1 > print(x) [1] 1 > x [1] 1 > x <- x+1 [1] 2 > msg <- "Oi"
O caractere # indica um comentário. Tudo a direita de # será tratado como um texto qualquer.
Quando uma expressão completa é adicionada no prompt, esta é avaliada e o resultado da expressão é retornado. Isso pode ocorrer automaticamente.
Colchetes ([n]
) na impressão indicam que a variável é um vetor e que o elemento, mostrado na linha, é do índice n
. No seguinte exemplo, [1]
indica que x
é um vetor, e 5
é seu primeiro elemento.
> x <- 5 # Nada será impresso > x # x é impresso automaticamente [1] 5 > print(x) # x é explicitamente impresso [1] 5
R tem cinco objetos ou classes “atômicas”:
1 - character
2 - numeric
3 - integer
4 - complex
5 - logical
Zero ou mais caracteres criados entre aspas. Note que, diferentemente de outras linguagens de programação, uma string em R é um aglomerado (não vetor) de caracteres chamado de character. Isto implica que o índice 1 retorna toda a string, e não o primeiro caractere. A função class()
retorna a classe (o tipo) do objeto.
> foo <- 'Isto é uma classe character, acredite' > class(foo) [1] "character" > nada <- '' > class(nada) [1] "character" > foo[1] [1] "Isto é uma classe character, acredite"
Mais conhecido como double ou float, tipos numéricos são tipos de dados que possuem representação pós-vírgula. Real ou decimal também são semelhantes que podem ser encontrados (exemplo: tipos de dados do MySQL). No R
, o tipo numérico com duas casas pós-vírgula de precisão é o padrão. Por exemplo, idade <- 20
gera a variável idade
que será do tipo numeric.
> valor <- 99.99 > class(valor) [1] "numeric" > valorAcao <- 20.99999 > valorAcao [1] 20.99999 > idade <- 20 > class(idade) [1] "numeric"
Um número inteiro positivo ou negativo. Não possuem representação pós-vírgula. Para explicitamente solicitar um inteiro, o sufixo L
se faz necessário. Como alternativa, podemos chamar a função integer()
.
> idade <- integer(20) > class(idade) [1] "integer"
…
Exemplo: A entrada 1
gera um objeto numérico com precisão decimal (numeric); a entrada 1L
explicitamente gera um inteiro.
> class(1L) [1] "integer"
Se quisermos converter um numeric para inteiro, poderemos usar round()
, trunc()
ou ceiling()
. Observe os exemplos abaixo.
> valorAcao <- 15.59 > round(valorAcao) #Valor inteiro mais próximo [1] 16 > trunc(valorAcao) #Valor inteiro sem a precisão decimal [1] 15 > ceiling(valorAcao) #Valor inteiro imediatamente superior [1] 16
Há um número especial Inf
que representa o infinito (isto também vale para tipos numéricos). Exemplos:
> 1/0 [1] Inf
O resultado Inf
pode ser usado para cálculos quaisquer. Por exemplo:
> 1/Inf [1] 0
Caso o número seja indefinido, teremos o valor NaN
(“not a number”).
Um número puramente imaginário. No exemplo abaixo, se não soubermos o que é i e não atribuirmos nenhuma operação a ele, z será um número complexo.
> z = 1 + 2i > class(z) [1] "complex"
Variável que guarda verdadeiro (TRUE) ou falso (FALSE) como resultado de uma expressão lógica.
> a <- 1; b <- 2 > x <- a > b > class(x) [1] "logical" > x [1] FALSE
…
Os valores 1 e 0 podem ser usados como representantes para, respectivamente, verdadeiro e falso. Por exemplo, usando a variável x
do código acima, temos:
> x == 0 [1] TRUE > x == 1 [1] FALSE
Saindo das classes atômicas, temos os objetos. Em R, o objeto mais básico é um vetor.
vector()
ou simplesmente adicionando conjuntos de dados a uma variável.class
irá retornar o tipo primitivo contido no vetor.c()
pode ser usada para criar vetores de objetos.> x <- c(0.5, 0.6) ## Numérico > x <- c(TRUE, FALSE) ## lógico > x <- c(T, F) ## lógico > x <- c("a", "b", "c") ## caractere > x <- 9:29 ## inteiro > x <- c(1+0i, 2+4i) ## complexo
…
> primos <- c(2,3,5,7,11) > primos [1] 2 3 5 7 11 > class(primos) [1] "numeric" > chuvaSol <- c(TRUE, FALSE, TRUE, FALSE, TRUE) > class(chuvaSol) [1] "logical"
…
…Também podemos usar a função vector()
> x <- vector("numeric", length = 10) > x [1] 0 0 0 0 0 0 0 0 0 0
Ao contrário da maioria das linguagens de programação, em R, vetores iniciam no índice 1. Veja o código abaixo (o segundo número primo é 3).
> primos[2] [1] 3
…
Também podemos solicitar uma consulta pela exclusão de um índice. Todos os números primos armazenados, menos o segundo.
> primos[-2] [1] 2 5 7 11
Operações lógicas ou aritméticas também pode ser aplicada para vetores inteiros, sem a necessidade de laços de repetição.
> primos*2 [1] 4 6 10 14 22 > primos*primos [1] 4 9 25 49 121 > primos+1 [1] 3 4 6 8 12
…
Algumas combinações são permitidas e, possivelmente, resultam em saídas não tão óbvias. Exemplo: o que acontece se somarmos o vetor numérico primos com o vetor lógico chuvaSol?
primos+chuvaSol
…
Os índices que sofreram incremento de 1 são os índices cujos elementos do vetor chuvaSol são verdadeiros. Isso acontece porque o R entende, mesmo em operações aritméticas, verdadeiro como 1 e falso como 0.
Finalmente, podemos combinar vetores.
> primosclima <- c(primos,chuvaSol) > primosclima [1] 2 3 5 7 11 1 0 1 0 1
…
> vetor_estranho <- c(1.7, "a") ## caractere > vetor_estranho <- c(TRUE, 2) ## numérico > vetor_estranho <- c("a", TRUE) ## caractere
Quando diferentes objetos são postos em um vetor, acontece a coerção e o vetor continua com um só tipo. Podemos fazer coerções explícitas, ou seja, objetos serão compelidos a uma outra classe via função as.*
(caso esteja disponível).
Quando diferentes objetos são postos em um vetor, acontece a coerção e o vetor continua com um só tipo. Podemos fazer coerções explícitas, ou seja, objetos serão compelidos a uma outra classe via função as.*
(caso esteja disponível).
Quais as saídas geradas pelos seguintes trechos de código?
> zeroanove <- 0:9 # Qual a classe? > foo <- as.numeric(zeroanove) > class(foo) [1] "numeric" > foo <- as.logical(zeroanove) > class(foo) [1] "logical" > foo ? > as.character(zeroanove) ?
Qualquer linguagem de programação/script que se preze tem um conjunto de estruturas comuns de seleção e repetição. Eis um breve resumo dessas estruturas em R.
Se( -condição-)então
a <- 5 b <- 4 > a <- 5 > b <- 4 > if(a == b){ + print(a) + }else{ print(b) } [1] 4
enquanto(-condição-)faça
> while(i > 1){ + print(i) + i <- i-3 + } [1] 9 [1] 6 [1] 3
para(-var- em -alcance-)faça
> for (i in 1:3){ + print(i*2) + } [1] 2 [1] 4 [1] 6
Perceba que o segundo parâmetro do laço é um vetor. Este pode ser criado por uma sequência (como no exemplo 1:3
), atribuido por uma variável (vetor), ou extraído de outros objetos que gerem um vetor (por exemplo, uma matriz ou um data frame).
Matrizes são coleções de dados organizadas em uma tabela de \(m\) linhas e \(n\) colunas. No R, matrizes possuem um atributo dimension que por si é um vetor de inteiros com tamanho 2 (\(m\) e \(n\)), indicando número de linhas e número de colunas (nrow, ncol).
No R, tendo as dimensões definidas, precisamos de uma linha de código.
> m <- 2 > n <- 3 > A <- matrix(nrow = m, ncol = n) > A [,1] [,2] [,3] [1,] NA NA NA [2,] NA NA NA
…
A função dim()
pode ser usada para verificar a dimensão de uma matriz.
> dim(A) [1] 2 3 > attributes(A) $dim [1] 2 3
…
Matrizes são construídas variando mais rapidamente o índice de suas linhas, use o parâmetro byrow=TRUE
para alterar a ordem. Os parâmetros passados são, respectivamente, vetor de dados, número de linhas (nrow) e número de colunas (ncol).
> A <- matrix(1:6, nrow = 2, ncol = 3) > A <- matrix(1:6, nrow = 2, ncol = 3, byrow = TRUE)
Do it!
- Verifique a matriz A para cada um dos códigos acima.
…
Matrizes também podem ser criadas diretamente de vetores por meio da transformação do atributo dim
(dimensões).
> A <- 1:10 > A [1] 1 2 3 4 5 6 7 8 9 10 > dim(A) <- c(2, 5)
Do it!
- Verifique a matriz A.
…
Matrizes podem ser criadas via column-binding ou row-binding com cbind()
e rbind()
.
> x <- 1:3 > y <- 10:12 > cbind(x, y) > A <- rbind(x, y)
Do it!
- Verifique as saídas.
…
Podemos resgatar um elemento de uma matrix pelos seus índices.
> A[2,3] # Elemento na segunda linha e na terceira coluna. y 12
Data frames são usados para armazenar dados estruturados de maneira tabular. Imagine um dataframe como uma matriz com propriedades extras como, por exemplo, nome das linhas e colunas.
Comumente, você usará arquivos .csv para armazenar dados. Carregar arquivos .csv (via função read.csv()
) gera um objeto data.frame
. Use head(X,n)
para ver as primeiras n
linhas de um data frame X
.
> X <- read.csv(url("http://www-usr.inf.ufsm.br/~joaquim/book_datasets/ classificacao_ex_GoT.csv")) > head(X,2) Pessoa Cabelo Peso Altura Genero 1 Tyrion Curto 45 130 M 2 John Comprido 65 170 M > class(X) [1] "data.frame"
…
As seguintes características são válidas para esta classe:
Pode ser considerada um tipo especial de lista (cada elemento possui o mesmo tamanho).
Também pode ser considerada como um tipo especial de matriz, onde cada coluna pode conter diferentes classes, e linhas e colunas podem conter rótulos (atributo names
para colunas, e row.names
para linhas).
As funções read.table()
ou read.csv()
geralmente são usadas para carregar arquivos para um data frame.
Pode ser convertida para matrizes por meio da chamada data.matrix()
.
Pode-se obter um data frame diretamente de uma matriz com data.frame()
.
…
> X <- data.frame(foo = 1:4, bar = c(T, T, F, F)) > X > nrow(X) > ncol(X) > A <- matrix(1:6, nrow = 2, ncol = 3, byrow=TRUE) > A > data.frame(A)
Do it!
- Verifique as saídas.
…
Uma coluna pode ser acessada usando o operador $
ou o segundo elemento nos colchetes [intParaLinha, intParaColuna]
.
> X$Peso [1] 45 65 100 55 110 70 80 58 65 56 > X[2,3] [1] 65
Em complemento às estruturas comuns de repetição, R conta com funções apply()
, especialmente úteis para matrizes ou data frames. Observe o código abaixo, com uma estrutura de repetição comum, usaríamos dois laços encadeados para fazer a média das colunas. O mesmo resultado pode ser obtido com sapply() (apply “simplificado”), mas com performance superior.
> X <- read.csv(url("http://www-usr.inf.ufsm.br/~joaquim/book_datasets/ classificacao_ex_GoT.csv")) > head(X,2) Pessoa Cabelo Peso Altura Genero 1 Tyrion Curto 45 130 M 2 John Comprido 65 170 M > sapply(X[,3:4],mean) Peso Altura 70.4 169.9
Uma lista é um tipo especial de vetor que contêm elementos de diferentes classes. Considere a lista como um vetor genérico que suporta outros tipos de elementos.
Exemplos:
> primos <- c(2,3,5,7,11) > primos [1] 2 3 5 7 11 > alphabeta <- c("a","b","c","d") > chuva <- c(TRUE, FALSE, TRUE, FALSE, TRUE) > X <- list(primos, alphabeta, chuva); X [[1]] [1] 2 3 5 7 11 [[2]] [1] "a" "b" "c" "d" [[3]] [1] TRUE FALSE TRUE FALSE TRUE > class(X) [1] "list"
Factors são usados para representar dados categóricos. Factors podem ser ordenados ou não. Pense em um factor de inteiros como um vetor (de inteiros), onde cada elemento possui um label (rótulo).
Factors são tratados especialmente por funções de modelagem como lm()
e glm()
.
Factors são autodescritivos, isso deixa as coisas mais claras em certos casos; é melhor ter uma variável “Masculino” e “Feminino” do que apenas valores representantes (exemplo: 1,2).
…
Exemplos:
> X <- factor(c("yes", "yes", "no", "yes", "no")) > X [1] yes yes no yes no Levels: no yes > table(X) X no yes 2 3 > unclass(X) [1] 2 2 1 2 1 attr(,"levels") [1] "no" "yes"
…
Alguns pacotes não entendem vetores binários diretamente, é necessária a conversão para factor
.
> X <- data.frame(foo = 1:4, bar = c(T, T, F, F)) > X foo bar 1 1 TRUE 2 2 TRUE 3 3 FALSE 4 4 FALSE > X$bar [1] TRUE TRUE FALSE FALSE > as.factor(X$bar) [1] TRUE TRUE FALSE FALSE Levels: FALSE TRUE
…
A ordem dos níveis pode ser ajustada pelo argumento levels
de factor()
. Isso pode ser importante para modelos em que o primeiro nível é usado como base.
> X <- factor(c("yes", "yes", "no", "yes", "no"), levels = c("yes", "no")) > X [1] yes yes no yes no Levels: yes no
Valores faltantes são descritos por NA
(Not Available) ou NaN
(Not a Number) para operações matemáticas não definidas.
is.na()
é usado para testar se objetos são NA
.
is.nan()
é usado para testar NaN
.
Valores NA
também possuem classe, inteiro NA
, caractere NA
, etc.
Um valor NaN
é também um NA
, mas o inverso não se aplica.
…
Exemplos:
> x <- c(9, 2, NA, 9, 3, 4) > is.na(x) [1] FALSE FALSE TRUE FALSE FALSE FALSE > is.nan(x) [1] FALSE FALSE FALSE FALSE FALSE FALSE > x <- c(1, 2, NaN, NA, 4) > is.na(x) [1] FALSE FALSE TRUE TRUE FALSE > is.nan(x) [1] FALSE FALSE TRUE FALSE FALSE
Vetores em R podem ter nomes.
> x <- 1:3 > names(x) NULL > names(x) <- c("foo", "bar", "norf") > x foo bar norf 1 2 3 > names(x) [1] "foo" "bar" "norf"
…
Assim como listas e outros objetos.
> x <- list(a = 1, b = 2, c = 3) > x $a [1] 1 $b [1] 2 $c [1] 3
R contém centenas de pacotes (ou bibliotecas) disponíveis para as mais diversas atividades.
Boa parte desses pacotes estão disponíveis no CRAN (Comprehensive R Archive Network), e podem ser instalados diretamente usando o comando install.packages()
.
Naturalmente, alguns pacotes são criados usando funções de outros pacotes. Isso cria um conjunto de dependências e faz com que a instalação de um pacote dispare um gatilho para a instalação de vários outros.
Por exemplo, para usar a função neuralnet()
para criar redes neurais, instale o pacote neuralnet
(neste caso, o mesmo nome) com install.packages("neuralnet")
e carregue-o com library(neuralnet)
.
…
Alguns desenvolvedores deixam pacotes disponíveis em links do Github. Para fazer a instalação desses pacotes, instale e carregue o pacote devtools
:install.packages("devtools")
; library(devtools)
.Devtools
possui uma função chamada install_github()
. Use install_github()
passando o nome do desenvolvedor e o nome do pacote como uma única string no parâmetro (exemplo, “devA/libX”).
Teste seu entendimento e vá em direção da fluência.
1 - Crie um vetor de caracteres com a sequência 1 ate 99. Chame de vet1.
2 - Crie uma matrix 4x4 com valores de 1 até 16. Chame de mat1.
3 - Crie um data frame com a matriz anterior. Chame de DF1.
4 - Coloque nomes nas colunas do data frame (‘a’,‘b’,‘c’,‘d’).
5 - Crie uma lista com a,b,c. Depois substitua o ‘b’ por 2. Chame de lista1.
6 - Verifique que, em lista1, 2 é um valor numérico.
7 - Use a função summary para prever dados de sua matriz.
8 - Use um laço para criar um vetor chamado vet2 com a fórmula: vet1[i](i0.8), onde i é o índice do laço (1 … 99).
9 - Use plot e hist para visualizar o vetor vet2.
10 - Verifique a média, mediana e o terceiro quartil do vetor vet2.
11 - Carregue um arquivo .csv usando as funções url e read.csv.