Aquisição de Dados

A principal motivação para se usar o R consiste em tratamento de dados. Devemos, portanto, ter formas eficientes para promover a leitura de dados para dentro de nosso ambiente. Já vimos que objetos como data frames podem ser editados por meio dos comandos edit(objeto) ou fix(objeto) que abrem uma janela para a alteração em forma de grade, permitindo inclusive a inserção de novos campos ou a alteração de nomes dos campos já existentes. Esta pode ser uma boa estratégia para se fazer pequenas alterações nas tabelas.

Outra função usada para leitura de dados do usuário ou à partir da leitura de um arquivo é scan().

scan(file = "", what = double(), n = -1, sep = "")
Valores listados para os parâmetros são default. Existem muitos outros parâmetros.
file = "" indica que a leitura será feita do teclado. Se file = "arquivo" este arquivo será lido.
what indica o tipo de dado a ser lido. what=character() significa que strings serão lidas.
n é o número de dados que serão inserido. n = -1 significa um número ilimitado. Neste caso a inserção (para n=-1) termina com dois <ENTER> seguidos.
sep = "" é o tipo de separador esperado. O default é um espaço em branco.
> x <- scan(n=3) # insere 3 valores do teclado
 1: 12 2: 23 3: 34
 Read 3 items
> x
[1] 12 23 34

Para a leitura de bases de dados mais extensas outras formas estão disponíveis. Uma delas consiste em realizar a leitura de um arquivo csv ( valores separados por vírgula, em inglês comma separated values). Este tipo de arquivo consiste em uma lista de linhas, cada uma delas contendo um número constante de valores, separados por vírgula (ou outro sinal). Estes arquivos podem ser lidos por gerenciadores de planilhas tais como o Excel ou o CALC, do Libre Office. Eles podem também ser gerados por estes aplicativos.

Vamos criar um arquivo para efeito de aprendizado dessa importação de dados. Em um editor de texto ASCII qualquer digitamos os valores seguintes:

id, Nome,  Sobrenome, Idade, Sexo
1,  Marta, Rocha,     24,    F
2,  Pedro, Souza,     12,    M
3,  José,  Marciano,  15,    M
4,  Joana, Santos,    21,    F
5,  Lucas, Pereira,   20,    M

O espaçamento entre os campos não é necessário. Digamos que gravamos este arquivo com o nome alunos.csv na pasta de trabalho em uso (ou em outra qualquer).

Estes dados podem ser lidos com o comando read.table:

read.table("nomeArquivo.csv", header=TRUE, sep=",", dec=".")Aqui o parâmetro header=TRUE indica que a primeira linha do arquivo contém títulos para as colunas, sep="," indica que as valores estão separados por vírgula (poderiam estar separados por outro caracter, como “;”) e dec="." indica que o ponto é o separador numérico de decimais. Se o arquivo não estiver na pasta de trabalho atual o nome completo ("caminho/nomearquivo.csv") deve ser fornecido.

Para a conveniência do usuário, diversas funções do R são acompanhadas de outras com nomes diversos que realizam as mesmas operações mas usam parâmetros default diferentes. É o caso de read.table() e read.csv(). Consulte a ajuda para ver quais são estes parâmetros.

Por default ítens numéricos são lidos como variáveis numéricas e texto como fatores, embora este comportamento possa ser alterado se necessário. A primeira linha (o cabeçalho) alimenta os valores de nomes de colunas.

> dir()
[1] "alunos.csv"
> alunos <- read.table("alunos.csv", header=TRUE, sep=",", dec=".")
> alunos
  id    Nome  Sobrenome Idade  Sexo
1  1   Marta      Rocha    24     F
2  2   Pedro      Souza    12     M
3  3    José   Marciano    15     M
4  4   Joana     Santos    21     F
5  5   Lucas    Pereira    20     M
> class(alunos)
[1] "data.frame"
> fix(alunos)     # permite a edição em uma tabela de alunos
> names(alunos)   # lista propriedades names
[1] "id"        "Nome"      "Sobrenome" "Idade"     "Sexo"     
> dim(alunos)     # dimensões da lista (5 linhas com 5 campos)
[1] 5 5
> alunos[1,]      # primeira linha da lista
  id    Nome Sobrenome Idade  Sexo
1  1   Marta     Rocha    24     F

> # O parâmetro row.names permite usar uma coluna para nomear as linhas:
> outroAlunos <- read.table("alunos.csv", header=TRUE,
                       row.names="id", sep=",")
> outroAlunos
N     Nome  Sobrenome Idade  Sexo
1   Marta      Rocha    24     F
2   Pedro      Souza    12     M
3    José   Marciano    15     M
4   Joana     Santos    21     F
5   Lucas    Pereira    20     M

Em muitos casos pode ser útil também fazer o processo inverso: a partir de uma tabela gravamos um arquivo csv para fins de exportação para outro aplicativo. Para isso usaremos, a seguir, a função write.csv()

> # Para recordar, criamos uma nova tabela, semelhante à alunos:
> alunos2 <- data.frame( id =1:5,
     Nome = c("Marta","Pedro","José","Joana","Lucas"),
     Sobrenome = c("Rocha","Souza","Marciano","Santos","Pereira"),
     Idade = c(24, 12, 15, 21, 20),
     Sexo = c("F", "M","M", "F", "M") )
> write.csv(alunos2)
# escrevendo no console
 "","id","Nome","Sobrenome","Idade","Sexo"
   "1",1,"Marta","Rocha",24,"F"
   "2",2,"Pedro","Souza",12,"M"
   "3",3,"José","Marciano",15,"M"
   "4",4,"Joana","Santos",21,"F"
   "5",5,"Lucas","Pereira",20,"M"
> # Para gravar esta tabela em disco, como um arquivo csv:
> write.csv(alunos2, file="alunos2.csv")

Para gravar o objeto alunos2 (uma lista) para uso futuro usamos save(). O objeto pode ser recuperado para o projeto através da função load().

> save(alunos2, file="alunos2.Rdata")
> dir()                   # Para verificar quais são os aqruivos na pasta
[1] "alunos.csv"       "alunos2.Rdata"
> rm(alunos2)             # alunos2 não existe mais na sessão
> load('alunos2.Rdata')   # recupera alunos2
> str(alunos2)
'data.frame':	5 obs. of  5 variables:
 $ id       : int  1 2 3 4 5
 $ Nome     : Factor w/ 5 levels "Joana","José",..: 4 5 2 1 3
 $ Sobrenome: Factor w/ 5 levels "Marciano","Pereira",..: 3 5 1 4 2
 $ Idade    : num  24 12 15 21 20
 $ Sexo     : Factor w/ 2 levels "F","M": 1 2 2 1 2

Alternativamente, podemos ler uma variável de texto para dentro de uma tabela.

> dados <- " idade sexo altura 13 F 1.25 15 F 1.60 10 M 1.40 "
> tabela <- read.table(header=TRUE, text=dados)
> str(tabela)
'data.frame':	3 obs. of  3 variables:
 $ idade : int  13 15 10
 $ sexo  : Factor w/ 2 levels "F","M": 1 1 2
 $ altura: num  1.25 1.6 1.4

Nos exemplos anteriores os tipos das colunas foram inferidos à partir dos dados lidos. Os campos de texto foram convertidos em fatores. O parâmetro colClasses permite que sejam informados previamente o tipo de cada coluna lida.

> alunosNotas <- "
     id| aluno |nota |bolsista
     1 | Marco | 5.2 |sim
     2 | Ana   | 7.5 |nao
     3 | Celia | 2.5 |sim"
> notas <- read.table(header=TRUE, text=alunosNotas,
         row.names="id", sep="|",
         colClasses=c("numeric", "character", "numeric", "character"))
> str(notas)
'data.frame':	3 obs. of  3 variables:
 $ aluno   : chr  " Marco " " Ana   " " Celia "
 $ nota    : num  5.2 7.5 2.5
 $ bolsista: chr  "sim" "nao" "sim"
> # A coluna bolsista foi importada como strings.
> # Para transformá-la em uma coluna de valores lógicos podemos fazer
> notas$bolsista <- notas$bolsista=="sim"
> str(notas)
'data.frame':	3 obs. of  3 variables:
 $ aluno   : chr  " Marco " " Ana   " " Celia "
 $ nota    : num  5.2 7.5 2.5
 $ bolsista: logi  TRUE FALSE TRUE

Importando planilhas

O pacote xlsx depende para seu funcionamento dos pacotes rJava e xlsxjars, bem como uma instalação funcional do Java em seu computador.

Para importar uma planilha do Excel ou Libre Office Spreadsheet podemos exportar estes dados para um arquivo *.csv e importá-lo usando as técnicas já descritas. Alternativamente é possível importar diretamente estas planilhas usando o pacote xlsx, que deve ser instalado antes do uso. Planilhas podem ser importadascom as funções read.xlsx e read.xlsx2 que têm a seguinte sintaxe:

read.xlsx(file, sheetIndex, sheetName=NULL, rowIndex=NULL,
    startRow=NULL, endRow=NULL, colIndex=NULL,
    as.data.frame=TRUE, header=TRUE, colClasses=NA,
    keepFormulas=FALSE, encoding=”unknown”, password=NULL, …)

read.xlsx2(file, sheetIndex, sheetName=NULL, startRow=1,
    colIndex=NULL, endRow=NULL, as.data.frame=TRUE, header=TRUE,
    colClasses=”character”, password=NULL, …)

Argumento Descrição
file arquivo (com caminho) a ser lido.
sheetIndex número da planilha dentro da pasta de trabalho.
sheetName nome da planilha.
rowIndex vetor numérico indicando linhas a serem extrarídas. Se NULL todas as linhas, exceto se startRow, endRow são especificados.
colIndex vetor numérico indicando colunas a serem extrarídas. Se NULL todas as colunas.
as.data.frame valor lógico. Se TRUE os dados serão montados em um data.frame. Se FALSE, uma lista, com um elemento por coluna.
header valor lógico indicando que a primeira linha contém os nomes das colunas.
colClasses (read.xlsx) vetor de strings com a classe de cada coluna.
keepFormulas valor lógico. Se TRUE as fórmulas do excel são mostradas como texto e não avaliadas.
encoding codificação para strings na planilha.
startRow numérico, especificando índice da 1ª linha. (Ativo se rowIndex=NULL).
endRow numérico, especificando índice da última linha. Se NULL, todas as linhas. (Ativo se rowIndex=NULL).
password senha para a pasta de trabalho.
outros argumentos para a data.frame. Ex. stringsAsFactors

A função read.xlsx procura adequar o tipo lido com o da planilha de acordo com cada coluna, preservando o tipo de dado lido.
read.xlsx2 é mais rápida, adequada para ser usada em planilhas muito grandes, acima de 100 mil células. Ambas podem ser usadas para ler arquivos *.xlsx ou *.xls.

> library(xlsx)
> xlFrame <- read.xlsx("planilha.xlsx",1, header=TRUE); xlFrame
     Data Local        Crédito   Débito
  1 43223 Casa Coral   1002.56   65.45
  2 43224 Fornecedor 1   23.34   NA
  3 43225 Cliente 2      24.34   33.00
  4 43226 Fornecedor 2   15.23   54.00
> # Valor não existente na planilha foi lido como 'NA'
> # A data foi lida como um campo numérico.

Gravando dados em uma planilha Excel

As funções write.xlsx e write.xlsx2 podem ser usadas para gravar dados de uma tabela em uma pasta de trabalho Excel. A segunda delas atinge uma performance melhor para planilhas longas, acima de 100 mil células.

Elas têm a sintaxe:

write.xlsx(x, file, sheetName=”Sheet1″,
    col.names=TRUE, row.names=TRUE,
    append=FALSE, showNA=TRUE, password=NULL)

write.xlsx2(x, file, sheetName=”Sheet1″,
    col.names=TRUE, row.names=TRUE,
    append=FALSE, password=NULL, …)

São seus argumentos:

Argumento Descrição
x data.frame a ser escrito como pasta de trabalho.
file arquivo (com caminho) a ser escrito.
sheetName nome da planilha.
col.names valor lógico. Se TRUE os nomes das colunas de x são escritos no arquivo.
row.names valor lógico. Se TRUE os nomes das linhas de x são escritos no arquivo.
append valor lógico. Se TRUE o arquivo é lido no disco e incrementado.
showNA valor lógico. Se FALSE valores NA são gravados em branco.
password senha para a pasta de trabalho.
outros argumentos passados para addDataFrame (no caso de read.xlsx2).

Para exibir o comportamento destas funções usamos o data.frame USArrests (que vem instalado no pacote básico de R).
Primeiro criamos uma planilha com nome USA-ARRESTS. Depois gravamos em outra planilha na mesma pasta o dataframe alunos que temos carregado em nossa sessão.

> write.xlsx(USArrests, file="pastaTrabalho.xlsx",
             sheetName="USA-ARRESTS", append=FALSE)
> write.xlsx(alunos, file="pastaTrabalho.xlsx",
             sheetName="alunos", append=TRUE)

O resultado é a gravação, em disco, de uma pasta de trabalho com duas planilhas com nomes USA-ARRESTS e alunos.

Existem outros pacotes destinados à manipulação de arquivos de planilhas. Entre eles citamos os pacotes XLConnect e openxlsx. Este último não depende de Java.


Operadores e Funções Internas

Laços e Funções do Usuário

Laços: Controle de Fluxo

O interpretador de R processa as linhas de comandos de modo sequencial, uma linha após a outra. Muitas vezes é necessário bifurcar o código ou repetir um conjunto de linhas, dependendo de certas condições. Para isso temos os laços (loops) e testes lógicos.

Teste lógicos if() e else
if(condicao){
    Instrucoes1
} else {
    Instrucoes2
}

A condição para o teste deve ser uma comparação lógica resultando em TRUE ou FALSE. Instrucoes1 serão executadas se a condição for verdadeira, Instrucoes2 caso contrário.

Teste vetorizado ifelse()
ifelse(condicão, valor1, valor1)
Retorna valor1 se condicao = TRUE, valor2 caso contrário.

Laço for()
for(condicao) {
    Instrucoes1 ...
}

A condição para os laços for devem ser sempre do tipo var in seq, onde a variável var percorre uma sequência.

Laço while()
while(condicao) {
    Instrucoes ...
}

Executa as instruções enquanto a condição for verdadeira. Deve-se ter o cuidado de providenciar um mecanismo de saída para este laço.

> # Teste if/else
> if (17 %% 2 == 0) {
     print("17 é par")
} else {
     print("17 é ímpar")
}
[1] "17 é ímpar"

> # ifelse
> ifelse(4==3, "é", "não é")
[1] "não é"
> ifelse(3==3, "é", "não é")
[1] "é"
> # A função ifelse realiza internamente um
> # loop nos componentes de um vetor (ou outro objeto)
> teste <- c(1,2.3,4,5.5, 2.3, 7.3, 0.9)
> resultado <- ifelse(teste > 5, "passou", "falhou")
> resultado
[1] "falhou" "falhou" "falhou" "passou" "falhou" "passou" "falhou"

> # laço for
> for(i in c(1,3,5,7)) {print(paste(i,"^2 = ",i^2, sep =""))}
[1] "1^2 = 1"
[1] "3^2 = 9"
[1] "5^2 = 25"
[1] "7^2 = 49"
> # Laço while
> n <- 1
> while(n < 5) {
    print(paste(n, "< 5"))
    n<-n+1
}
[1] "1 < 5"
[1] "2 < 5"
[1] "3 < 5"
[1] "4 < 5"
Laço repeat()
repeat() {
    Instrucoes ...
}

Executa as instruções indefinidamente. Uma saída para este laço pode ser forçada com a instrução break, listada a seguir.

Instrução break: força a saída de um laço
Instrução next: pula uma iteração do laço (retornando para seu início)
Instrução return: retorna o valor de uma função

Instrução switch()
switch(expr, valor1, ..., valorn)
Se expr é um inteiro i, retorna valori
Se expr é um string str, os demais argumentos devem nomeados e switch retorna valor correspondente ao name = str.

> # Laço repeat, o mesmo que while(TRUE)
n <- 1
> repeat {
    print(paste(n, "< 4"))
    n <- n+1
    if(n == 4) break
}
[1] "1 < 4"
[1] "2 < 4"
[1] "3 < 4"
> # Saltando dentro de um laço
> for (i in 1:10) {
    if(i<4 | i>6) next
     print(i)
}
[1] 4
[1] 5
[1] 6

> # Uso de switch() com argumento inteiro:
> for (i in 1:4) print(switch(i,"um", "dois", "três", "quatro" ))
[1] "um"
[1] "dois"
[1] "três"
[1] "quatro"
> # Uso de switch() com argumento de string:
> sinto <- c("medo", "alegria")
> for (i in sinto) {
     print(
     switch(i, triste = "alegre-se", 
               medo = "calma", alegria = "aproveita")
     )
  }
[1] "calma"
[1] "aproveita"

Funções do Usuário

O usuário pode criar funções em R de acordo com suas necessidades. Elas geralmente servem para armazenar uma série de instruções que será utilizada repetidamente ou apenas para organizar um bloco de código mais complexo. Funções possuem a seguinte estrutura básica:

funcao <- function(arg1, ..., argn) {
     lista de Instrucoes
     return(objeto)
}

A instrução return é opcional. Se omitida a função retornará o resultado da última operação realizada. Os colchetes podem também ser omitidos se a função consiste em apenas uma linha de código.

A função é chamada fornecendo-se seus argumentos
funcao(varg1, ..., argn)
Quando ela retorna um valor que será usado em seguida atribuímos seu valor a uma variável:
var <- funcao(arg1, ..., argn)

Qualquer objeto, ou nenhum, pode ser retornado pela função. Quanto aos argumentos eles podem ou não ser nomeados. Argumentos não nomeados devem ser identificados pela sua posição na chamada da função. Se forem nomeados eles podem receber valores default na definição da função que serão usados caso sejam omitidos na invocação da função.

> funcao1 <- function(x, y) {
            z <- x+y
            return(x + y^z) }
> funcao1(2, 3)
[1] 245
> # O mesmo resultado seria obtido se omitíssemos a instrução return:
> funcao1 <- function(x, y) x + y^(x+y)

> # Com argumentos nomeados e com valores default:
> funcao2 <- function(inicio=1,fim=10) {
             v <- inicio:fim
             return(v) }
> funcao2()
 [1]  1  2  3  4  5  6  7  8  9 10
> funcao2(5)  # apenas o primeiro arg é fornecido
[1]  5  6  7  8  9 10
> funcao2(,5)  # segundo arg é reconhecido pela posição
[1] 1 2 3 4 5
> funcao2(fim=13)  # segundo arg é reconhecido pelo nome
[1]  1  2  3  4  5  6  7  8  9 10 11 12 13
> # A instrução return não é obrigatória,
> # nem os colchetes para uma função de única linha
modulo <- function(z) sqrt(Re(z)^2 + Im(z)^2)
> modulo(4+5i)
[1]  6.40312
> # A função tratará, sempre que possível, qualquer tipo de argumento
> funcao3 <- function(x, y) { return(x + y) }
> funcao3(c(1,2,3), c(4,5,6))
[1] 5 7 9
> # Você pode visualizar a constituição de uma função
> funcao1
function(inicio=1,fim=10) {return(inicio:fim)}
> # Para exibir seus argumento use:
> args(funcao1)
function (inicio = 1, fim = 10)
NULL

Pode-se também especificar que um argumento é nulo se não for declarado explicitamente na chamada da função como, por exemplo, em: f <- function(a, b = 1, c = NULL) {}. Neste caso deve-se testar no corpo da função se o argumento foi fornecido, antes de usá-lo. É importante notar que uma variável inicializada dentro do corpo de definição da função tem seu escopo limitado à esta função (e não pode ser usada fora dela).

O argumento ... (3 pontos) tem um significado especial em R. Ele indica que um número indeterminado de argumento podem ser passados para a função e é particularmente útil quando existe outra função aninhada (com muitos argumentos) no corpo da primeira.

> montarLinha <- function(x, ...){
                 print(paste("Existem ", x, "cores:", ...))
                 }
> montarLinha(3, "vermelho", "verde", "azul")
[1] "Existem  3 cores: vermelho verde azul"

Função podem ser aninhadas, ou seja, é possível chamar uma função de dentro de outra funcão:

> funcao1 <- function(txt) { return(paste("modificação 1: ",txt))}
> funcao2 <- function(txt, t2=NULL) {
             retorna <- ""
             if (is.character(txt)) {
                 retorna <- paste("modificação2: ", funcao1(txt))
             } else {
                 retorna <- "Argumento deve ser um string..."
             }
             if (!is.null(t2)) retorna <- paste(retorna,"!")
             return(retorna)
  }
> print(funcao2(2))
[1] "Argumento deve ser um string..."
> print(funcao2("testando"))
[1] "modificação2:  modificação 1:  testando"
> print(funcao2("Inserindo o 2o argumento", 1))
[1] "modificação2:  modificação 1:  Inserindo o 2o argumento !"

Funções podem retornar qualquer um dos objetos de R, inclusive outras funções:

> potencia <- function(ordem) {
              f <- function(x) {x ^ ordem}
              return(f)
              }
> quarta <- potencia(4)    # define a função f(x) = x^4
> quarta(2)
[1] 16
> quadrado <- potencia(2)  # define a função f(x) = x^2
> quadrado(15)
[1] 225

Observação: Fizemos uso das funções is.character(var) e is.null(var) que testam, respectivamente, se a variável var é do tipo character ou null. Muitas outras funções de teste existem e são muito úteis, principalmente em scripts. Associadas a elas estão as funções de conversão que forçam a transformação de um tipo em outro, quando possível.

Algumas destas funções estão listadas abaixo:

Teste Conversão
is.numeric() as.numeric()
is.character() as.character()
is.vector() as.vector()
is.matrix() as.matrix()
is.data.frame() as.data.frame()
is.factor() as.factor()
is.logical() as.logical()
is(var, type) as(var, type)
> is.character("1")          # TRUE
> is("1", "character")       # TRUE
> is("1", "numeric")         # FALSE
> is(1, "numeric")           # TRUE
> is(1i, "complex")          # TRUE
> n <- as("125", "numeric")  # n = 125
> is.logical(1==2)           # TRUE
> is.vector(1:2)             # TRUE
> is.vector("1")             # TRUE (um vetor com um componente)
> as.logical(1)              # TRUE (as.logical(0) = FALSE
> dt<- as.Date("2018-11-25") # dt = "2018-11-25"
> class(dt)                  # "Date"


Aquisição de Dados

Operadores e Funções Internas

Operadores

Os seguintes operadores matemáticos estão definidos em R:

Operador Descrição Exemplo
+ adição
subtração
* multiplicação
/ divisão 3/2 = 1.5;
^ ou ** exponenciação 3^2 = 6, 2**3 = 8
%% módulo 9 %% 2 = 1
%/% divisão inteira 9 %/% 2 = 4

Os seguintes operadores lógicos estão definidos:

Operador Descrição Exemplo
< menor que 5 < 7 = TRUE
<= menor ou igual 3 <= 9 = TRUE
> maior que 5 > 7 = FALSE
>= maior ou igual 7 >= 7 = TRUE
== igual 3 == 5 = FALSE
!= diferente 3 != 5 = TRUE
!x não x !(7 < 3) = TRUE
x | y x ou y c(T, T, F) & c(T, F, F) = (T, T, F)
x || y ou (apenas 1º elemento examinado) c(T, F, F) || c(F, F, F) = TRUE
x & y x e y c(T, T, F) & c(T, F, F) = (T, F, F)
x & y e (apenas 1º elemento examinado) c(T, F, F) && c(F, F, F) = FALSE
isTRUE(x) verifica se x é TRUE isTRUE(7 < 9) = TRUE

Outros operadores:

Operador Descrição Exemplo
: (dois pontos) cria uma sequência de números 2:6 = (2, 3, 4, 5, 6)
%in% pertence 3 %in% 1:4 = TRUE,5 %in% 1:4 = FALSE
%*% multiplicação de matrizes por sua transposta A %*% t(A)
any(condição sobre x) TRUE se algum elemento de x satisfaz a condição any(x==9)
all(condição sobre x) TRUE se todos os elementos de x satisfazem a condição all(x!=9)

Nos elementos de um vetor as operações ocorrem entre componentes de mesma posição em cada vetor.

> # Usando dois vetores de mesmo comprimento
> u <- c(1,2,3,4,5) > v <- c(5,4,3,2,1) > u+v
[1] 6 6 6 6 6
> u-v
[1] -4 -2  0  2  4
> u*v
[1] 5 8 9 8 5
> u**v
[1]  1 16 27 16  5
> u %% v
[1] 1 2 0 0 0
> u %/% v
[1] 0 0 1 2 5
> media <- (u + v) / 2 > media
[1] 3 3 3 3 3

> # Se os operandos têm comprimentos diferentes então um deve
> # ter comprimento múltiplo do outro. n cópias do vetor menor
> # serão usadas na operação e o resultado terá o tamanho do maior.
> u + c(1,2,3)
[1] 2 4 6 5 7
Warning message:
In u + c(1, 2, 3) :
  longer object length is not a multiple of shorter object length
> u + 10
[1] 11 12 13 14 15
> w <- c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) > u+w
 [1]  2  4  6  8 10  7  9 11 13 15
 w/u
[1]  1.000000 1.000000 1.000000 1.000000 1.000000
[6]  6.000000 3.500000 2.666667 2.250000 2.000000

># Lembrando que u = (1,2,3,4,5)
> any(u > 4)
[1] TRUE
> any(u > 5)
[1] FALSE
> all(u < 4)
[1] FALSE

Comparações lógicas entre vetores também são efetuadas entre elementos, um a um.

> u > v
[1] FALSE FALSE FALSE  TRUE  TRUE
> x <- 1:10 > x
 [1]  1  2  3  4  5  6  7  8  9 10
> x[x < 3 | x > 7]
[1]  1  2  8  9 10
> x[x > 2 & x < 8] [1] 3 4 5 6 7 > # O operador %in% busca valores entre todos de um vetor
> # Lembrando que u = (1, 2, 3, 4, 5)
> 1 %in% u
[1] TRUE
> 6 %in% u
[1] FALSE

Lembrando que x = 1:10, vamos verificar com maior detalhe a operação:
x[x < 3 | x > 7] = (1, 2, 8, 9, 10)
Por partes:
x < 3 = (T, T, F, F, F, F, F, F, F, F)
x > 7 = (F, F, F, F, F, F, F, T, T, T)
x < 3 | x > 7 = (T, T, F, F, F, F, F, T, T, T)
Finalmente
x[(T, T, F, F, F, F, F, T, T, T)] = (1, 2, 8, 9, 10)
Portanto selecionamos os componentes do vetor x que são menores que 3 ou maiores que 7.

Operações pode ser realizadas entre membros de outros objetos compostos. Por exemplo, usando um data frame:

> mdata<-data.frame(x = c(2, 2, 6, 4), y = c(3, 4, 2, 8)) > mdata
   x  y
1  2  3
2  2  4
3  6  2
4  4  8
> attach(mdata)
> mdata$soma <- x + y > mdata$media <- (x + y)/2 > detach(mdata)
> # As operações acima acrescentaram dois novos campos à mdata:
> mdata
   x  y  soma  media
1  2  3    5   2.5
2  2  4    6   3.0
3  6  2    8   4.0
4  4  8   12   6.0
> # O mesmo tipo de operação pode ser feita de forma
> # alternativa usando-se a função transform
> valores <- data.frame(x=c(1,4,6,8), y=c(1,3,5,7)) > valores <- transform(valores, soma = x+y, media = (x+y)/2, teste = x>y)
> valores
  x y soma media teste
1 1 1    2   1.0 FALSE
2 4 3    7   3.5  TRUE
3 6 5   11   5.5  TRUE
4 8 7   15   7.5  TRUE

Funções internas

Quase toda a funcionalidade do R é obtida através de funções. Um grande número delas faz parte do bloco básico, carregado por default, e muitas outras podem ser utilizadas através da instalação de pacotes (packages).

Funções numéricas

Função Descrição
abs(x) \(\left|x\right|\), valor absoluto
sqrt(x) \(\sqrt x\), raiz quadrada
ceiling(x) menor inteiro acima: ceiling(3.475) = 4
floor(x) maior inteiro abaixo: floor(3.475) = 3
trunc(x) truncamento: trunc(5.99) is 5
round(x, digits=n) arredondamento: round(3.475, digits=2) = 3.48
signif(x, digits=n) n dígitos significantes: signif(3.475, digits=2) = 3.5
cos(x), sin(x), tan(x) funções trigonométricas, seno, cosseno, tangente
acos(x), cosh(x), acosh(x) outras funções trigonométricas
log(x) \(\ln(x)\) logaritmo natural (base e)
log10(x) \(\log(x)\), logaritmo de base 10
exp(x) \(e^x\), exponencial

Funções de texto

Função Descrição
substr(x, a, b) retorna ou substitui parte de uma string x, da posição a até b.
sub(texto1, texto2, x) substitui, na string x, o texto1 pelo texto2.
grep(padrao, x , ignore.case=FALSE, fixed=FALSE) Procura padrao em x. Se fixed = FALSE o padrão é uma expressão regular, caso contrário um texto simples. Retorna índice de localização.
strsplit(x, sep) Quebra o vetor x em sep.
paste(…, sep=”-“) Concatena strings usando a string sep como separator.
toupper(x) retorna texto em letras maiúsculas
tolower(x) retorna texto em letras minúsculas
nchar(x) retorna o comprimento da string x
> # Retornar uma substring
> substr("abcdef",3,5)
[1] "cde"
> # Substituir caracteres
> sub("strings", "texto", "Trocar strings")
[1] "Trocar texto"
> # Partir texto
> strsplit("as casas de maria", " ")
[[1]]
[1] "as"  "casas"  "de"  "maria"
> strsplit("ABCDEF", "BC")
[[1]]
[1] "A"   "DEF"
> strsplit("ABCDEF", "")
[[1]]
[1] "A" "B" "C" "D" "E" "F"
> # As funções agem em todos os comonentes do objeto
> x <- c("estudar", "R", "no site") > substr(x,1,2)
[1] "es" "R"  "no"

> # Uso se expressão regular
> s <- "www.phylos.net" > sub("p.+s","filosofia", s)
[1] "www.filosofia.net"

> toupper("falando alto")
[1] "FALANDO ALTO"
> tolower("Não GRITE")
[1] "não grite"

> # Para juntar strings:
> paste("primeiro", "segundo", "terceiro")
[1] "primeiro segundo terceiro"
> paste("primeiro", "segundo", "terceiro", sep = ", ")
[1] "primeiro, segundo, terceiro"
> # Valores numéricos são convertidos em strings
> paste(1,2,3, sep="-")
[1] "1-2-3"
> paste(1,2,3, sep="")
[1] "123"
> paste("tentativa", 1)
[1] "tentativa 1"
> tent <- paste("tentativa", 1:5) > tent[5]
[1] "tentativa 5"

Funções Auxiliares Úteis

Função Descrição
seq(from, to, by) gera sequência numérica (início, fim, passo)
rep(x, times=n) repete x n vezes
cut(x, n) divide variável contínua (numérica) em fator com n níveis
pretty(x,n) divide variável contínua em n intervalos
cat( , file = nomeArquivo, append = FALSE) concatena objectos em e os envia para o console ou arquivo nomeArquivo (se existir)
> seq(12, 30, 2)
[1] 12 14 16 18 20 22 24 26 28 30
> # Forçando o resultado a ter 5 elementos
> seq(from=0, to=20, length.out=5)
[1]  0  5 10 15 20

> rep("ha", times=4)
[1] "ha" "ha" "ha" "ha"
> # Repetindo cada elemento n vezes
> rep(c(1,2,3), each=2)
[1] 1 1 2 2 3 3
> $ Repete o primeiro elemento 4 x, o segundo 2 x
> rep(c("a", "b"), times = c(4,2))
[1] "a" "a" "a" "a" "b" "b"

> # cut permite a criação de fator. Abaixo, com 4 níveis:
> idades <- c(12, 14, 16, 17, 34, 32, 12, 12, 11) > cut(idades, breaks=4)
[1] (11,16.8]   (11,16.8]   (11,16.8]   (16.8,22.5] (28.2,34]
[5] (28.2,34]   (11,16.8]   (11,16.8]   (11,16.8]
Levels: (11,16.8] (16.8,22.5] (22.5,28.2] (28.2,34]
> # Uso de pretty
> pretty(1:20, n=2)
[1]  0 10 20
> pretty(1:20, n=10)
[1]  0  2  4  6  8 10 12 14 16 18 20
> # Uso de cat
> nome <- "Ana" > cat("Olá",nome,"\b.\n", "\t \"Bom dia!\"")
Olá Ana.
 	 "Bom dia!"

Para exibir o comportamento de cat() usamos as sequências de escape \n (newline), \b (backspace), \t (tab), \" (aspas duplas)

Funções úteis para a manipulação de Objetos

Listamos em seguida algumas das funções importantes para a leitura e edição de objetos.

Função Descrição
length(obj) retorna o número de elementos ou componentes do objeto
dim(obj) retorna as dimensões do objeto.
str(obj) exibe a estrutura do objeto.
head() lista os seis primeiros elementos do objeto
tail() lista os seis últimass elementos do objeto
class(obj) retorna a classe do objeto.
mode(obj) exibe como o objeto foi armazenado
names(obj) exibe os nomes de componentes do objeto
c(obj1, …, objn) concatena objetos em um vector
cbind(obj1, …, objn) combina objetos em colunas
rbind(obj1, …, objn) combina objetos em linhas
obj, print(obj) exibe / imprime objeto.
head(obj) lista a primeira parte do objeto
tail(obj) lista a parte final do objeto
ls() exibe lista dos objetos carregados
rm(obj1, …, objn) remove um ou mais objetos
rm(list = ls()) )remove todos os objetos
novoObj <- edit(obj) edita objeto e o armazena como novoObj
fix(obj) edita objeto salvando nele as alterações

Data e Hora

Datas são armazenadas internamente no R como o número de dias decorridos desde 01/01/1970. Datas anteriores são representadas como números negativos.

Função Descrição
as.Date(string) converte a string em uma data
Sys.Date( ) retorna a data de hoje
date() retorna data e hora corrente
data2 – data1 retorna a diferença entre data1 e data2 em dias
as.character(data) retorna a data como um string
format(data, format=strDeFormato) formata a data segundo o string de formatação
weekdays(data) dia da semana correspondente a data (ou datas)
months(data) mês não abreviado correspondente a data (ou datas)
quarters(data) Quarter (Q1, Q2, Q3, Q4)
seq(from=data1, to=data2, by=n) sequência de datas de data1 até data2, em passos n (dias)
> # Data do sistema (um string, formato ano/mês/dia)
> Sys.Date()
[1] "2018-11-23"
> # Transforma esta string em uma data
> data1 <- as.Date(Sys.Date()) > # Soma 250 dias à data1
> data2 <- data1 + 250 > data2 - data1
[1] Time difference of 250 days
> # Sequência de datas começando em data1 até data2 com passos de 50 dias
> seq(from=data1, to=data2, by=50)
[1] "2018-11-23" "2019-01-12" "2019-03-03"
[4] "2019-04-22" "2019-06-11" "2019-07-31"
> # Produz sequência de datas de data1 até data2 com 5 elementos
> seq(from=data1, to=data3, length.out=5)
[1] "2018-11-23" "2019-01-24" "2019-03-28"
[4] "2019-05-29" "2019-07-31"
> weekdays(data1)
[1] "sexta"
> months(data1)
[1] "novembro"
> quarters(data1)
[1] "Q4"
> format(data1, "%d/%m/%y")
[1] "23/11/18"
> format(data1, "%d/%m/%Y")
[1] "23/11/2018"
> format(data1, "%A, %d de %B de %Y")
[1] "sexta, 23 de novembro de 2018"
> # As funções se aplicam a vetores e outros objetos
> strData <- c("01/05/1965", "08/16/1975") > datas <- as.Date(strDatas, "%m/%d/%Y") > datas
[1] "1965-01-05" "1975-08-16"
> Para lidar com o formato brasileiro de dia/mes/ano podemos fazer
> dBr <- as.Date("23/11/2018", "%d/%m/%Y") > dBr
[1] "2018-11-23"

Os seguintes símbolos (ou máscaras) podem ser usados com datas. Os resultados dependem das configurações de data/hora locais, que podem ser visualizadas com o comando Sys.localeconv().

Símbolo Descrição Exemplo
%d dia, numérico 01 a 31
%a dia da semana, abreviado Mon, (Seg)
%A dia da semana por extenso Monday (segunda)
%m mês, numérico 01 a 12
%b nome do mês, abreviado Feb, (Fev)
%B nome do mês por extenso February, (Fevereiro)
%y ano em 2 dígitos 18
%Y ano em 4 dígitos 2018

Funções Estatísticas

Função Descrição
mean(x, trim=0,na.rm=FALSE) média do objeto x
sd(x) desvio padrão do objeto x
var(x) variância
mad(x) desvio absoluto médio
median(x) mediana
quantile(x, probs) quantil de x, probs= vetor numérico com probabilidades em [0,1]
range(x) intervalo
sum(x) soma
diff(x, lag=1) diferenças defasadas, lag = defasagem a usar
min(x) mínimo de x
max(x) máximo de x
scale(x, center=TRUE, scale=TRUE) centro da coluna ou padronizar uma matriz
> x <- c(123, 234, 345, 242, 34, 100, NA) > mean(x)
[1] NA
> # mesma operação ignorando valor NA
> mean(x, na.rm=TRUE)
[1] 179.6667
> # redefinindo x
> x <- c(123, 234, 345, 242, 34, 100) > sum(x)
[1] 1078
> range(x)
[1]  34 345
> min(x)
[1] 34
> max(x)
[1] 345
> mean(x)
[1] 179.6667
> # Eliminando valores 20% nas bordas da amostra
> mean(x, trim=.2)
[1] 174.75
> sd(x)
[1] 113.9731
> var(x)
[1] 12989.87
> mad(x)
[1] 105.2646
> median(x)
[1] 178.5

A tabela seguinte lista funções relacionadas com distribuições probabilísticas. Para gerar sequências pseudo-randômicas (que podem ser replicadas mais tarde) use set.seed(1234) (ou outro inteiro).

Função Descrição
dbinom(x, size, prob)
pbinom(q, size, prob)
qbinom(p, size, prob)
rbinom(n, size, prob)
distribuição binomial,
onde size = tamanho da amostra e prob é probabilidade
de sucesso em cada experimento.
dpois(x, lambda)
ppois(q, lambda)
qpois(p, lambda)
rpois(n, lambda)
Distribuição de Poisson com m=std=lambda
dunif(x, min=0, max=1)
punif(q, min=0, max=1)
qunif(p, min=0, max=1)
runif(n, min=0, max=1)
Distribuição uniforme, segue mesmo padrão
que a distribuição normal acima.

Voltaremos ao estudos destas funções mais tarde.

A Distribuição Normal

Por completeza listamos aqui algumas funções de distribuição de probabilidades. As funções de densidade, de distribuição, quantil e a geração aleatória para a distribuição normal podem ser obtidas com média e desvio padrão especificados.

A função rnorm gera dados aleatórios com distribuição normal:dnorm(x, mean = 0, sd = 1, log = FALSE)
pnorm(q, mean = 0, sd = 1, lower.tail = TRUE, log.p = FALSE)
qnorm(p, mean = 0, sd = 1, lower.tail = TRUE, log.p = FALSE)
rnorm(n, mean = 0, sd = 1)

São argumentos:

x, q vetor de quantils.
p vetor de probabilidades.
n número de observações. Se length(n) > 1, the length is taken to be the number required.
mean vetor de médias.
sd vetor de desvios padrão.
log, log.p logical; se TRUE, probabilidades são dadas como log(p).
lower.tail logical; se TRUE (default), probabilidades são P[X ≤ x]; caso contrário, P[X > x].

Se a média e o desvio padrão não são especificados eles assumem o valor default 0 e 1, respectivamente.

A distribuição normal tem densidade:

$$
f(x) = \frac{1}{\sigma \sqrt{2\pi}} \text{e}^{-\frac{(x-\mu)^2}{2\sigma ^2}}
$$

onde \(\mu\) é a média da distribuição e \(\sigma\) é o desvio padrão.

dnorm fornece a densidade, pnorm a função de distribuição, qnorm a função quantil, rnorm gera os desvios aleatórios. O comprimento do resultado é determinado por n para rnorm. Para as demais funções ele é igual ao maior comprimento dos argumentos numéricos.

Os argumentos numéricos (exceto de n) são reciclados para o tamanho do resultado. Apenas os primeiros elementos dos argumentos lógicos são usados.

> x <- pretty(c(-3,3), 100)
> y <- dnorm(x)
> plot(x, y, type = "l", xlab = "Desvio Normal", ylab = "Densidade")
Distribuição normal

Este código gera o gráfico exibido à direita. Veremos em breve maiores detalhes sobre o uso da função plot() usada para gerar o gráfico.

A distribuição normal é uma das mais utilizadas na modelagem dos fenômenos naturais e das ciências naturais e sociais. Ela é também chamada de distribuição de Gauss ou de Laplace–Gauss, em referência aos matemáticos Pierre-Simon Laplace (1749-1827) e Carl Friedrich Gauss (1777-1855).


Funções do Usuário

Data Frames

Dataframes são uma generalização de matrizes onde cada coluna pode ser de um tipo ou classe diferente de dados. Neste sentido este é o objeto de R que mais se aproxima de uma planilha ou de um banco de dados.

Um dataframe pode conter nomes para as colunas, uma indicação de que dado está nela armazenado, e também um atributo especial chamado row.names que guarda informações sobre cada uma de suas linhas. Eles podem ser criados explicitamente com a função data.frame() ou através da transformação forçada de outros tipos de objetos, como as listas. Por sua vez eles podem ser transformados em matrizes data.matrix().

Muitas vezes um dataframe é carregado diretamente através da leitura de dados gravados previamente por meio de comandos como read.table() ou read.csv().

Vamos criar um dataframe contendo os dados de alunos, contendo um id, nome, idade e menção final (II, MI, MM, MS, SS), expostos na tabela seguinte:

id Nome Idade Menção
1 Paulo 24 MM
2 Joana 23 MS
3 Marcos 19 MM
4 Fred 21 II
5 Ana 20 MI

Estes dados podem ser inseridos em um dataframe da seguinte forma:

> id <- 1:5
> nome <- c("Paulo", "Joana", "Marcos", "Fred", "Ana")
> idade <- c(24, 23, 19, 21, 20)
> mencao <- c("MM", "MS", "MM", "II", "MI" )
> alunos <- data.frame(id, nome, idade, mencao)
> alunos
  id   nome idade mencao
1  1  Paulo    24     MM
2  2  Joana    23     MS
3  3 Marcos    19     MM
4  4   Fred    21     II
5  5    Ana    20     MI
> # As entradas no frame podem ser consultadas de várias maneiras
> alunos["mencao"]
  mencao
1     MM
2     MS
3     MM
4     II
5     MI
> alunos[c("nome", "mencao")]
    nome mencao
1  Paulo     MM
2  Joana     MS
3 Marcos     MM
4   Fred     II
5    Ana     MI
> alunos$mencao
[1] MM MS MM II MI
Levels: II MI MM MS

Observe que a coluna de menções (bem como a de nomes) foi transformada em um fator, não ordenado. Em situações em que o uso de um dataframe é recorrente as funções attach(), detach() e with() podem ser bastante úteis.

A função attach() informa ao interpretador de R qual é o dataframe default a que se referem os campos citados no código. A função detach() remove esta ligação. Seu uso é opcional mas é uma boa prática de programação que deve ser seguida.

attach(alunos)
The following objects are masked _by_ .GlobalEnv:
    id, idade, mencao, nome
> id
[1] 1 2 3 4 5
> summary(idade)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
   19.0    20.0    21.0    21.4    23.0    24.0 
> table(mencao)
mencao
II MI MM MS 
 1  1  2  1 
> detach(alunos)

Quando a função attach foi executada o interpretador informou que os campos id, idade, mencao, nome receberam máscaras para sua execução. Se outra variável previamente definida tinha o mesmo nome ela terá precedência na busca pelo interpretador (o que pode não ser o comportamento desejado). Para evitar tais possíveis conflitos podemos usar with(). Desta forma se garante que todos os comandos dentro das chaves se refiram à alunos.

> with(alunos, {
      print(idade)
      print(mencao)
  })
[1] 24 23 19 21 20
[1] MM MS MM II MI
Levels: II MI MM MS
> # Se um único comando será usado as chaves são opcionais
with(alunos, summary(idade))
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max.
   19.0    20.0    21.0    21.4    23.0    24.0
> # a função summary faz uma estatística básica dos dados do argumento

> # Para que a atribuição continue existindo fora das chaves usamos <<-
> with(alunos, {
        estatistica <<- summary(idade)
        estat <- summary(idade)
  })
> estatistica
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
   19.0    20.0    21.0    21.4    23.0    24.0 
> estat
Error: object 'estat' not found
> # A mesma dataframe pode ser criada com a atribuição de labels
> # às suas linhas. No caso atribuímos o id a este label
> alunos <- data.frame(id, nome, idade, mencao, row.names = id)
> # Estes labels são usados para exibição de dados e gráficos

> # O dataframe pode ser ordenado por ordem de idade dos alunos
> alunos <- alunos[order(alunos$idade),]
> alunos
  id   nome idade mencao
3  3 Marcos    19     MM
5  5    Ana    20     MI
4  4   Fred    21     II
2  2  Joana    23     MS
1  1  Paulo    24     MM

> # O número de linhas e colunas podem ser obtidos
> nrow(alunos)
[1] 5
> ncol(alunos)
[1] 4

> # O data frame pode ser criado vazio, com os campos especificados
> df <- data.frame(id=numeric(0), nome=character(0), nota=numeric(0))
> df
[1] id   nome nota
<0 rows> (or 0-length row.names)
> # e editado na janela edit
> df <- edit(df)
Funções usadas com dataframes
Função Efeito
df <- data.frame(vetor1, ... , vetorn) cria um dataframe
df[obj1] exibe a coluna relativa à obj1
attach(df) liga as variáveis ao dataframe df
detach(df) remove ligação ao dataframe df
with(df, {comandos}) executa comandos com ligação ao dataframe df
summary(obj1) retorna estatística básica dos dados de obj1
nrow(df) retorna número de linhas de df
ncow(df) retorna número de colunas de df
edit(df) abre uma janela para a edição do data frame
O operador edit() permite a edição de dados e dos nomes de campos de um data frame (ou de outros objectos de R, como vetores e matrizes).
Ele, no entanto, deixa o objeto inalterado. Para que as alterações sejam passadas para o mesmo objeto devemos fazer
obj <- edit(obj)
O mesmo resultado pode ser conseguido com o operador fix():
fix(obj) # alterações já ficam gravados em obj


Operadores e Funções Internas

Listas e Fatores

Listas (lists)

Listas (lists) são uma generalização dos vetores que podem conter elementos de classes diferentes.

> lista1 <- list(234, "casa", 1+2i, TRUE)
> lista1
[[1]]
[1] 234
[[2]]
[1] "casa"
[[3]]
[1] 1+2i
[[4]]
[1] TRUE

> lista1[2]
[[1]]
[1] "casa"

> lista1[3] <- "novo valor"

> lista2 <- vector("list", length=4)
> lista2[1] <- 1
> lista2[2] <- "popula"
> lista2[3] <- "a lista"
> lista2[4] <- True
> lista2
[[1]]
[1] 1
[[2]]
[1] "popula"
[[3]]
[1] "a lista"
[[4]]
[1] TRUE

> # A função list concatena os argumentos, que podem ser vetores
> v1 <- c(1,3,5)
> v2 <- c("1", "3", "5")
> v3 <- c(T, F)
> lista3 <- list(v1, v2, v3)
> lista3
[[1]]
[1] 1 3 5
[[2]]
[1] "1" "3" "5"
[[3]]
[1]  TRUE FALSE
> # Várias listas podem ser concatenadas
> listona <- list(lista1, lista2, lista3)
> # O segundo elemento da terceira lista é
> listona[[3]][[2]]
[1] "1" "3" "5"
> # Uma lista pode ter seus objetos nomeados
> lista4 <- list(impares=c(1,3,5,7,9), pares=c(2,4,6,8))
> lista4
$impares
[1] 1 3 5 7 9

$pares
[1] 2 4 6 8

> # Cada objeto pode ser recuperado por seu nome de duas formas
> lista4$pares
[1] 2 4 6 8
> lista4["pares"]
$pares
[1] 2 4 6 8
> # As duas notações acima são equivalentes à chamar o segundo objeto da lista
> lista4[2]
$pares
[1] 2 4 6 8

> # A lista pode ser criada com o atributo title (título)
> # juntamente com os nomes dos objetos anexados
> alunos <- list(title="Alunos", nome=c("Pedro", "Maria", "Jonas", "Raquel"),
            idade=c(17, 19, 14, 20))
> alunos
$title
[1] "Alunos"

$nome
[1] "Pedro"  "Maria"  "Jonas"  "Raquel"

$idade
[1] 17 19 14 20

> A lista tem os atributos
> names(alunos)
[1] "title"  "nome"  "idade"
> # Um atributo pode ser alterado dinamicamente
> alunos["title"]<-"Alunos - 2018"
> names(alunos)[2]<-"Apelidos"
> # A lista fica da seguinte forma:
> alunos
$title
[1] "Alunos - 2018"

$apelidos
[1] "Pedro"  "Maria"  "Jonas"  "Raquel"

$idade
[1] 17 19 14 2

Listas são importantes para a organização de dados inicialmente coletados de forma confusa ou desorganizada. Além disso muitas funções em R retornam listas que devem ser manipuladas para uma completa análise destes resultados.

Resumimos os comandos usados:

Função Efeito
lista <- list(obj1, … ,objn) cria uma lista com objetos de tipos diversos
lista <- vector("list", length=n) cria uma lista vazia de comprimento n
lista <- list(nome1=vetor1,…, nomen=vetorn) cria uma lista com atributos nome para cada vetor
lista[nome1] recupera o vetor1
list(title=”titulo”, obj1, … ,objn) cria uma lista com atributo title = “titulo”
names(lista) exibe os atributos da lista

Fatores (factors)

Fatores (factors) são variáveis ​​em R que assumem um número finito e discreto de valores. Elas ​​são também chamadas de categorias ou tipos enumerados e são muito usadas na modelagem estatística. Fatores são armazenados como um vetor de inteiros associado a outro vetor de caracteres, usados ​na exibição dos fatores. Um fator é criado com a função factor que recebe como argumento um vetor numérico ou de caracteres. No entanto os níveis de um fator sempre serão strings (caracteres ou literais).

Os níveis possíveis de um fator podem ser exibidos através do comando levels. Fatores são exibidos em ordem alfabética por default. Para alterar esta ordem de exibição o argumento levels pode receber um vetor com os valores possíveis na ordem desejada. A função table recebe um fator como argumento e retorna uma tabela com uma contagem de cada ítem do fator.

> x <- factor(c("sim", "não", "não", "não","sim", "sim"))
> x
[1] sim não não não sim sim
Levels: não sim
> table(x)
x
não sim
  3   3
> # A ordem de exibição pode ser alterada após a criação do fator
> y <- c("fraco", "normal", "forte", "forte", "forte", "normal")
> cafe <- factor(y)
> cafe <- factor(cafe, levels=c("fraco","normal","forte"))
> table(cafe)
cafe
 fraco normal  forte
     1      2      3
> # Os níves podem ser exibidos separadamente
> levels(cafe)
[1] "fraco"  "normal" "forte"
> # Um nível pode ser colocado em primeiro lugar
> relevel(cafe, "forte")
[1] fraco  normal forte  forte  forte  normal
Levels: forte fraco normal

Pode ocorrer que um conjunto de dados contenha uma tabela de informações codificadas numericamente. Suponha, por exemplo, que o resultado de um questionário tenha armazenado os códigos 1 = "masculino" e 2 = "feminino". Neste caso podemos fazer com que variáveis numéricas sejam armazenadas como factors usando as opções levels e labels.

> sexo <- c(1, 1, 1, 2, 1, 2, 2, 2, 1)
> table(sexo)
sexo
1 2
5 4
> sexo <- factor(sexo, levels = c(1,2), labels=c("masculino","feminino"))
> table(sexo)
sexo
masculino  feminino
        5         4
> # Note que a ordem dos labels deve corresponder à ordem dos levels.
> # Para alterar os dados (ou inserir novos) os labels devem ser usados
> sexo[3] <- "feminino"
> sexo[10] <- "masculino"
> sexo[11] <- "deconhecido" # um erro é gerado e o valor NA inserido

Apesar da ordem de exibição imposta aos fatores acima, todos eles são todos não ordenados. Fatores ordenados devem ser usados se comparações entre eles for necessária. Para isso usamos o argumento opcional ordered = TRUE.

medidas <-c("grande","gigante", "grande","gigante",
            "gigante","médio","grande","gigante",
            "pequeno","pequeno","grande","gigante")
> medidas
 [1] "grande"  "gigante" "grande"  "gigante" "gigante" "médio"   "grande"  "gigante" "pequeno"
 [10] "pequeno" "grande"  "gigante"
> niveis <-c("pequeno","médio","grande","gigante")
> tamanho <- factor(medidas, levels=niveis,ordered = TRUE)
> tamanho
 [1] grande  gigante grande  gigante gigante médio   grande
 [8] gigante pequeno pequeno grande  gigante
Levels: pequeno < médio < grande < gigante
> table(tamanho)
tamanho
pequeno   médio  grande gigante
      2       1       4       5

> # A ordem de um fator pode ser invertida
> tamanho2 <- factor(tamanho, levels=rev(levels(tamanho)))
> levels(tamanho2)
 [1] "gigante" "grande"  "médio"   "pequeno"
> table(tamanho2)
tamanho2
gigante  grande   médio pequeno
      5       4       1       2
Função Efeito
fator <- factor(vetor) cria uma lista de fatores
table(fator) exibe os fatores em forma de tabela
fator <- (fator, levels=vetor) ordena a ordem de exibição dos fatores
levels(fator) exibe a ordem de exibição dos fatores
fator <- factor(fator, levels=vetor1, labels=vetor2)

substitui os níveis em vetor1 com texto em vetor2
fator <- factor(fator, levels=vetor1, ordered = TRUE) cria fatores ordenados de acordo com vetor1
Observação: Variáveis podem ser nominais, ordinais ou contínuas. As nominais são categorias sem nenhuma ordenação. Um exemplo seriam modelos de automóveis, em uma tabela. Variáveis ordinais são formadas por texto mas com uma ordem definida. Um exemplo é a variável tamanho usada acima. Variáveis contínuas podem assumir qualquer valor, em geral dentro de limites estabelecidos.


Data Frames

Matrizes e Arrays

Matrizes

Para uma revisão sobre matrizes na Álgebra Linear veja Matrizes

Uma matriz é um objeto de duas dimensões, um conjunto de elementos organizados em linhas e colunas. Todos os componentes de uma matriz devem ser do mesmo tipo. Uma matriz Mm×n contém m linhas e n colunas. Em R uma matriz pode ser criada à partir de um vetor, através da função matrix():

> # Criando uma matriz de 4 linhas e 5 colunas
> n <- matrix(1:20, nrow=4, ncol=5) 
> n
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    5    9   13   17
[2,]    2    6   10   14   18
[3,]    3    7   11   15   19
[4,]    4    8   12   16   20
> # Por default as colunas são preenchidas por colunas.
> # Para preencher por linhas fazemos
> m <- matrix(1:20, nrow=4, ncol=5, byrow=TRUE) 
> m
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    2    3    4    5
[2,]    6    7    8    9   10
[3,]   11   12   13   14   15
[4,]   16   17   18   19   20
> # Os elementos podem ser lidos diretamente
> m[3,4]
[1] 14
> # A n-ésima linha pode ser obtida (fazendo n=2)
> m[2,]
[1]  6  7  8  9 10
> # A n-ésima coluna pode ser obtida (n=3)
> m[,3]
[1]  3  8 13 18
> # O segundo elemento da terceira coluna é
> m[,3][2]
[1] 8
> # O mesmo que 
> m[2,3]
[1] 8
> # Mais de uma coluna pode ser extraída
> # Extraindo a 1a e 3a coluna da matriz m
> m [, c(1,3)]
     [,1] [,2]
[1,]    1    3
[2,]    6    8
[3,]   11   13
[4,]   16   18
> # Uma matrix também pode ser declarada sem ter seus elementos definidos
> matr <- matrix(nrow=3,ncol=2)
> matr
     [,1] [,2]
[1,]   NA   NA
[2,]   NA   NA
[3,]   NA   NA
> # NA é a forma de R representar que o valor não está disponível
> # A matrix  pode ser populada em seguida:
> matr[1,1] <- 1
> matr[1,2] <- 4     # etc.
> # Matrizes, como vetores, possuem atributos.
> attributes(m)
$ dim
[1] 4 5
> # A matriz m possui apenas o atributo dimensão
> dim(m)
[1] 4 5
> # 4 linhas e 5 colunas.
> # Uma matriz pode ser criada associando-se dimensões à um vetor
> k <- 1:10
> k
[1]  1  2  3  4  5  6  7  8  9 10
> dim(k) <- c(2,5)
> k
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    3    5    7    9
[2,]    2    4    6    8   10
> # Finalmente matrizes podem ser criadas por agrupamento de colunas
> x <- 1:3
> y <- 10:12
> cbind(x,y)
     x  y
[1,] 1 10
[2,] 2 11
[3,] 3 12
> # ou agrupamento de linhas
> rbind(x,y)
  [,1] [,2] [,3]
x    1    2    3
y   10   11   12
> # Os argumentos de rbind e cbind são vetores ou matrizes.
> # Por ex., se xy = rbind(x,y) então
> rbind(x,xy)
  [,1] [,2] [,3]
x    1    2    3
x    1    2    3
y   10   11   12
> # As dimensões devem ser compatíveis ou os argumentos podem ser truncados
> rbind(xy, 100:104)
  [,1] [,2] [,3]
x    1    2    3
y   10   11   12
   100  101  102
Warning message:
In rbind(xy, 100:104) :
  number of columns of result is not a multiple of vector length (arg 2)
> # Uma mensagem de erro foi gerada.
>
> # Uma matrix pode ser criada com atributos m linhas, n colunas
> # juntamente com nomes para as linhas e colunas
> celulas <- c(11, 12, 21, 22)
> nomesLinhas <- c("Linha 1", "Linha 2")
> nomesColunas <- c("Coluna 1", "Coluna 2")
> matriz <- matrix(celulas, nrow=2, ncol=2, byrow=TRUE,
                   dimnames=list(nomesLinhas, nomesColunas))
> matriz
        Coluna 1 Coluna 2
Linha 1       11       12
Linha 2       21       22
>
> # Esta matriz tem atributos dim (dimensões 2X2) e dimnames
> attributes(matriz)
$dim
[1] 2 2

$dimnames
$dimnames[[1]]
[1] "Linha 1" "Linha 2"

$dimnames[[2]]
[1] "Coluna 1" "Coluna 2"
> # Os nomes das linhas e colunas podem ser lidos e alterados
> colnames(matriz)
[1] "Coluna 1" "Coluna 2"
> colnames(matriz) <- c("col1", "col2")
> row.names(matriz)
[1] "Linha 1" "Linha 2"
> row.names(matriz) <- c("lin1" , "lin2")
> # Agora a matriz tem novos atributos names
> matriz
     col1 col2
lin1   11   12
lin2   21   22
> # O nome de uma linha (ou coluna) pode ser alterado isoladamente
> row.names(matriz)[2] <- "linha dois"
> matriz
           col1 col2
lin1         11   12
linha dois   21   22

Os seguintes funções foram usadas para a criação, acesso e manipulação de matrizes:

Função Efeito
M = matrix(vetor, nrow=m, ncol=n, byrow=TRUE) cria matriz Mm x n usando os elementos do vetor, distribuídos por linhas
matriz[m,n] retorna o elemento Mm,n
matriz[m,n] <- q associa o valor q ao elemento Mm,n
matriz[m,] retorna a m-ésima linha da matriz M
matriz[,n] retorna a n-ésima coluna da matriz M
attributes(M) exibe atributos da matriz M
rbind(x, y) junta por linhas os objetos x, y
cbind(x, y) junta por colunas os objetos x, y
colnames(M) exibe (ou atribue) nomes para as colunas de M
row.names(M) exibe (ou atribue) nomes para as linhas de M

Arrays

Arrays são generalizações dos objetos matrizes e são manipulados de forma semelhante. Um array de dimensões 2 × 3 × 5 pode ser visto como uma coleção de 5 matrizes 2 × 3. Para efeito de sua representação no console elas são representadas exatamente desta forma.

> arr <- array(1:12, c(2, 3, 2))
> arr
, , 1

     [,1] [,2] [,3]
[1,]    1    3    5
[2,]    2    4    6

, , 2

     [,1] [,2] [,3]
[1,]    7    9   11
[2,]    8   10   12
> # Como vemos acima o componente [,, 2] é uma matriz 2 por 3
> arr[,,2]
     [,1] [,2] [,3]
[1,]    7    9   11
[2,]    8   10   12
> # que tem na primeira linha e segunda coluna o valor
> arr[,,2][1,2]
[1] 9
>
> # Um array pode ser construído com seus atributos names
> # Um ex, a terceira dimensão do array representa valores em anos diversos
> dim1 <- c("Filho 1","Filho 2")
> dim2 <- c("Educação", "Saúde", "Alimentação")
> dim3 <- c("2010", "2011")
> Despesas <- array(, c(2, 3, 2), dimnames=list(dim1, dim2, dim3))
> # Todos os elementos são 'NA'Despesas
> Despesas[1,1,1]<-90.80
> Despesas[1,1,2]<-98.80
> Despesas
, , 2010

        Educação Saúde Alimentação
Filho 1     90.8    NA          NA
Filho 2       NA    NA          NA

, , 2011

        Educação Saúde Alimentação
Filho 1     98.8    NA          NA
Filho 2       NA    NA          NA

> Despesas["Filho 1",,]
            2010 2011
Educação    90.8 98.8
Saúde         NA   NA
Alimentação   NA   NA

> Despesas["Filho 1","Saúde","2010"]<-456
> Despesas["Filho 1","Saúde","2010"]
[1] 456
> Despesas["Filho 1",,]
             2010 2011
Educação     90.8 98.8
Saúde       456.0   NA
Alimentação    NA   NA


Listas e fatores.

Tipos de dados, variáveis e vetores

Tipos de dados

Em R existem os seguintes tipos de dados e variáveis:

Tipo de Dado Exemplo
Lógico (Logic) TRUE, FALSE
Numérico (Numeric) 12.3, 5, 999
Inteiro (Integer) 2L, 34L, 0L
Complexo (Complex) 1 + 2i
Caracter (Character) ‘a’, “Bom dia”, “TRUE”, ‘23.4’
(Raw) “Bom dia” is stored as 42 6f 6d 20 64 69 61

Com estes dados (e variáveis) se pode construir objetos predefinidos e mais complexos: eles são os escalares* (scalars), vetores (vectors), matrizes (matrices), arrays (matrizes em dimensões maiores que m × n), data frames e listas (lists).

Com frequência mencionaremos o nome de uma entidade em inglês para facilitar a leitura dos textos abundantes na internet. Em alguns casos podemos manter a nomenclatura original, em inglês.
Observe que R é sensível ao caso. TESTE, Teste e teste são variáveis diferentes. Os valores lógicos devem ser escritos em maiúsculas (mas podem ser abreviados para T e F).
*Em R não existem, de fato, escalares. Eles são representados por vetores com um único componente.

Variáveis e vetores

e <- 154 # um escalar, numérico
l <- "pedro" # um escalar, caracter

a <- c(1, 3, 9.5, 6, -2, 4) # vetor numérico
b <- c("um", "dois", "três") # vetor de caracter
c <- c(TRUE, TRUE, FALSE, TRUE, FALSE) # vetor lógico

Todos os componentes de um vetor devem ser do mesmo tipo.

> # um escalar pode ser criado assim:
> x <- 10
> x
[1] 10
> print(x)
[1] 10
> # um vetor é criado usando o operador c()
> vetor_numerico <- c(1.2, 3.4, 5, 7, 8)
> vetor_numerico
[1] 1.2 3.4 5.0 7.0 8.0
> vetor_string <- c("a", "b", "c", "d")
> vetor_string
[1] "a" "b" "c" "d"
> vetor_logico <- c(FALSE, TRUE, TRUE)
> vetor_logico
[1] FALSE  TRUE  TRUE
> vetor_inteiros <- c(12L, 15L, 18L)
> vetor_inteiros
[1] 12 15 18
> # a classe de um objeto pode ser consultada com a função class()
> class(vetor_inteiros)
[1] "integer"
> class(vetor_logico)
[1] "logical"
> # O primeiro componente do vetor_numerico é
> vetor_numerico[1]
[1] 1.2
> # Seu comprimento
> length(vetor_numerico)
[1] 5
> # Podemos então obter seu último componente
> vetor_numerico[length(vetor_numerico)]
[1] 8
> # O terceiro e o quinto componentes são
> vetor_numerico[c(3, 5)] # 2nd and 4th elements of vector
[1] 5 8
> # O vetor v = (1, 2, 3, 4, 5, 6) pode ser criado com
> v <- c(1:6)
> v
[1] 1 2 3 4 5 6
> # Desta forma podemos obter 4 (por ex.)
> # elementos sequenciados de vetor_numerico
> vetor_numerico[(1:4)]
[1] 1.2 3.4 5.0 7.0
# Um componente pode ser alterado a qualquer momento
> vetor_numerico[1] <- 0
> vetor_numerico
[1] 0.0 3.4 5.0 7.0 8.0
# Novos componentes podem ser inseridos
> vetor_numerico[6] <- 203
> vetor_numerico
[1]   0   3   5   7   8 203
> Observe que o operador c concatena vetores
> frutas <- c("maçã","laranja")
> verduras <- c("alface", "brocolis","couve")
> c(frutas, verduras)
[1] "maçã"  "laranja"  "alface"  "brocolis"  "couve"

> # Em R um objeto é dinâmicamente modificado para acomodar uma atribuição
> w <- 1:3
> w[7] <- 17
> w
[1]  1  2  3 NA NA NA 17
NA é uma constante interna representando um valor ausente ou não disponível, Not Available.

Diferente do que ocorre na maioria das linguagens de programação os índices são contados à partir de 1 (e não 0).

Usamos os seguintes novos operadores:

Operador Efeito
v <- c(a1, ..., an) cria* o vetor v = (a1, ..., an)
v <- c(1:6) cria o vetor v = (1, 2, 3, 4, 5, 6)
v[r] retorna o r-ésimo componente, ar
v[c(p, q)] retorna componentes ap e aq
v[r] <- 5 substitui o valor de ar
v[q] <- 15, para q > n insere o valor aq
lenght(v) retorna o comprimento do vetor, lenght(v) = n.
*Mencionamos que o operador c concatena vetores.

Como já foi usado acima, podemos filtrar um vetor para pegar apenas alguns de seus componentes. Para ilustrar esta operação vamos criar um longo vetor e, a partir dele construir outro vetor apenas com algumas de suas componentes:

> u <- 1:10 # forma resumida de c(1:10)
> filtro <- c(T,T,T,F,F,F,T,T,T,F) # resumindo T = TRUE, F = FALSE
> u[filtro]
[1] 1 2 3 7 8 9
> # Observe ainda que podemos excluir o terceiro elemento
> u[-3]
[1]  1  2  4  5  6  7  8  9 10
> # ou todos os elementos entre o terceiro e o quinto, inclusive
> u[-3:-5]
[1]  1  2  6  7  8  9 10
> # Podemos atribuir este vetor filtrado a outra variável, para uso futuro
> novo_u <- u[-3:-5]
> # e remover o antigo, caso ele não seja mais necessário
> rm(u)
> # A função seq fornece uma forma adicional de criar um vetor
> # onde se fornece os valores inicial e final e o acréscimo (ou passo)
> v2 <- seq(from=0, to=3, by=.25)
> v2
[1] 0.00 0.25 0.50 0.75 1.00 1.25 1.50 1.75 2.00 2.25 2.50 2.75 3.00
> # Um vetor pode ser repetido dentro de outro vetor maior
> v <- 1:3    # um shortcut para c(1:3)
> rep(v, times=3)
[1] 1 2 3 1 2 3 1 2 3
# Para repetir cada componente 2 vezes
> rep(v, each=2)
[1] 1 1 2 2 3 3
> # Podemos especificar quantas vezes cada componente deve ser repetido
> rep(c(0, 7), times = c(4,2))  # repetir o primeiro componente 4 x, o segundo 2
[1] 0 0 0 0 7 7
> rep(v, times = c(1,0,3))
[1] 1 3 3 3
> # Repetir um vetor até obter outro de comprimento length.out
> rep(v,length.out=7)
[1] 1 2 3 1 2 3 1
> # Além das funções rep e seq podemos usar:
> # any: testa se algum elemento do vetor satisfaz uma condição
> any(v > 2)
[1] TRUE
>  any(v >= 4)
[1] FALSE
> # all: testa se todos os elementos do vetor satisfazem uma condição
> all(v > 2)
[1] FALSE
>  all(v >= 0)
[1] TRUE

Resumindo, usamos:

Função Efeito
rep(v, times = n) repete o vetor v n vezes
rep(v, times = c(r, s)) repete o primeiro componente r vezes, o segundo s vezes
rep(v, each = n) repete o vetor v, cada componente n vezes
rep(v, lenght.out = l) repete o vetor v até atingir um vetor de comprimento l
any(v condição) verifica se algum componente de v satisfaz à condição
all(v condição) verifica se todos os componentes de v satisfazem à condição

Para concluir esta sessão observamos que um vetor vazio pode ser criado através da função vector(). O vetor pode ser populado em seguida. Além disso vetores possuem o atributo names que é também um vetor. Ele permite atribuir nomes aos componentes do vetor, como mostrado abaixo:

> # Cria um vetor vazio (inicialmente um vetor lógico)
> v <- vector()
> v
logical(0)
> # Popula o vetor v
> v[1] <- 1
> v[2] <- 2
> v[3] <- 3
> v
[1] 1 2 3
> is.vector(v)
[1] TRUE
# Nenhum valor foi associado a names
> names(v)
NULL
> # Popula o vetor names associado a v
> names(v)[1] <- "primeiro"
> names(v)[2] <- "segundo"
> names(v)[3] <- "terceiro"
> v
primeiro  segundo terceiro
       1        2        3
> # Alternativamente
> names(v) <- c("um", "dois" ,"três")
> v
  um dois três
   1    2    3
> # O vetor continua sendo um vetor numérico
> class(v)
[1] "numeric"
> # Um vetor pode ser criado com seu atributo names definido
> v <- c('a'=1, 'b'=2, 'c'=3)
> names(v)
[1] "a" "b" "c"
> # As aspas acima são opcionais.
> # O mesmo efeito seria obtido com v <- c(a=1, b=2, c=3)
> v
a b c
1 2 3
> # Como dito, names é um vetor. Seu primeiro componente é
> names(v)[1]
[1] "a"
> # É possível obter o componente do vetor pelo seu atributo
> pessoa <- c("nome"="Pedro","Sobrenome"="Malazartes")
> pessoa["nome"]
   nome
"Pedro"


Matrizes e Arrays.

Estudos sobre o software estatístico R

Introdução ao R

R é uma linguagem de programação especialmente voltada para o tratamento de dados e estatística. É um software livre e de código aberto (free and open source), desenvolvido pelos estatísticos Ross Ilaka e Robert Gentleman a partir de 1993, inicialmente como um subconjunto da linguagem S. Em sua instalação básica R contém um grande número de funções estatísticas (modelagem linear e não linear, testes estatísticos clássicos, análise de séries temporais, classificação, agrupamento e muitos outros) e voltadas para a geração gráficos amplamente customizáveis. Além disso sua funcionalidade pode ser estendida por meio da instalação de pacotes (packages) muitos deles criados e disponibilizados por usuários. Tanto os pacotes de instalação como as extensões podem ser encontradas no site CRAN, The Comprehensive R Archive Network.

Pode-se interagir com R diretamente através de comandos de linha em um terminal ou por meio de alguns IDEs (ambientse de desenvolvimento integrados). Neste estudo usaremos o RStudio que pode ser baixado neste link.

Ao ser iniciado o ambiente do RStudio vemos uma informação de licença e algumas instruções básicas de uso. O prompt de comando é representado por um sinal (>), onde podemos inserir os comandos. Por exemplo, o comando help() abre as páginas de ajuda que aparecem, por default, no canto inferior esquerdo da tela. O comando help.start() acessa páginas html em CRAN e q() encerra a sessão do Studio. Um histórico dos comandos usados fica armazenado na pasta de trabalho em um arquivo oculto .Rhistory. Durante a sessão, ou quando ela é reiniciada, estes comandos ficam disponíveis e podem ser acessados usando as setas e do teclado.

R version 3.5.1 (2018-07-02) -- "Feather Spray"
Copyright (C) 2018 The R Foundation for Statistical Computing
Platform: x86_64-pc-linux-gnu (64-bit)

R is free software and comes with ABSOLUTELY NO WARRANTY.
You are welcome to redistribute it under certain conditions.
Type 'license()' or 'licence()' for distribution details.

  Natural language support but running in an English locale

R is a collaborative project with many contributors.
Type 'contributors()' for more information and
'citation()' on how to cite R or R packages in publications.

Type 'demo()' for some demos, 'help()' for on-line help, or
'help.start()' for an HTML browser interface to help.
Type 'q()' to quit R.

[Workspace loaded from ~/Projetos/R/.RData]

Usaremos o console e suas respostas para introduzir alguns conceitos. As instruções contendo atribuições e funções podem ser separadas por linhas ou por ponto-e-vírgula (;). Os comentários em R, que são linhas que são ignoradas pelo interpretador, são marcados uma linha de cada vez, com o sinal #.

> # Escolher uma pasta de trabalho
> setwd("/home/usuario/Projetos/R")
> # Verificar a atual pasta de trabalho
> getwd()
[1] "/home/usuario/Projetos/R"
> # Criar uma nova pasta de trabalho
> dir.create("teste")
> setwd("/home/usuario/Projetos/R/teste")
> getwd()
[1] "/home/usuario/Projetos/teste"
> # Atribuição de valor à uma variável
> x <- 1; y <- 2
> # Operações podem ser feitas interativamente
> x + y
[1] 3
> # Se o código estiver rodando de dentro de um arquivo
> print(x + y)
[1] 3
> # O estado da atual sessão pode ser gravado
> save.image("sessao1.R")
> # A sessão pode ser mais tarde recuperada com o comando
> load("/home/usuario/Projetos/teste/sessao1.R")

A Área de Trabalho (Workspace) de R é o ambiente em uso durante uma sessão, incluindo os pacotes carregados, variáves e funções definidas pelo usuário, incluindo os objetos vetores, matrizes, data frames e listas. Uma imagem do workspace atual pode ser salva ao final de uma sessão. Ela será automaticamente recuperada quando a sessão for reiniciada. O diretório (ou pasta) de trabalho atual será usado (por default) por R para ler ou gravar arquivos e dados. Para ler ou gravar em outra pasta o caminho completo deve ser fornecido. A tabela abaixo reune alguns comandos usados para a manipulação do ambiente de trabalho em R:

Comando: Resultado:
getwd() pasta atual
setwd(“pasta”) altera pasta atual
dir.create(“teste”) cria a pasta teste
dir() lista arquivos na pasta atual
save.image(“arquivo.R”) grava estado da sessão em arquivo.R
load(“arquivo.R”) recupera a sessão gravada em arquivo.R
ls() lista os objetos carregados na workspace atual
rm(objectlist) remove um ou mais objetos
help(options) fornece informação sobre as opções disponíveis
options() exibe e modifica as opções disponíveis
history(#) exibe os últimos # commandos (default = 25)
savehistory(“myfile”) grava o histórico de comandos no arquivo myfile (default =.Rhistory)
loadhistory(“myfile”) recupera o histórico de comandos no arquivo myfile (default = .Rhistory)
save.image(“myfile”) grava o workspace no arquivo myfile (default = .RData)
save(objectlist, file=”myfile”) grava objetos específicos em um arquivo
load(“myfile”) carrega para a sessão atual o workspace
q() encerra a sessão de R. (o usuário pode então salvar o workspace.)
Vimos também que o operador de atribuição em R é (diferente da maioria das demais linguagens de programação) <-.Atribuições também podem ser feitas da seguinte forma
r = 5
98 -> kk .
Estas não são práticas recomendadas, por convenção.

Maiores ajudas sobre uma função pode ser obtida:

Operador de ajuda Efeito
help.start() ajuda geral
help(“foo”) (ou ?foo) ajuda sobre a função foo (aspas optionais)
help.search(“foo”) or ??foo busca pela string ‘foo’ no sistema de ajuda
example(“foo”) exemplos de uso da função foo
RSiteSearch(“foo”) busca pela string ‘foo’ no sistema de ajuda online e mailing lists
vignette() lista todas as vignettes disponíveis para os pacotes instalados
vignette(“foo”) lista todas as vignettes disponíveis para o tópico “foo”
data() lista todos os exemplos disponíveis de conjunto de dados contidos nos pacotes instalados

Vignettes são artigos introdutórios em formato pdf disponíveis para alguns pacotes.

Palavras Reservadas em R

Palavras Reservadas Uso
If, else, repeat, while, function, for, in, next, break Usados em loops, condicionais e funções
TRUE, FALSE Constantes lógicas
NULL Valor ausente ou indefinido
Inf Infinito
NaN Not a Number (não número)
NA Not Available (não disponível)
NA_integer_, NA_real_, NA_complex_, NA_ character_ Constantes de vetores com valores ausentes
Permite que uma função passe argumentospara outra

Regras e convenções para nomes de Variáveis

Para dar nomes às variáveis em R existem algumas regras e algumas convenções. Nomes válidos consistem de letras, números, pontos ou underline. A variável deve começar com uma letra ou ponto não seguido de número e não devem ser palavras reservadas.
Como convenção se pode usar:

Tipo Exemplo
apenas letras minúsculas idadealuno
palavras separadas por . idade.aluno
palavras separadas por _ idade_aluno
CamelCase minúsculas idadeAluno
CamelCase maiúsculas IdadeAluno

É aconselhável que um dos estilos seja escolhido e usados de forma consistente.

Pacotes (Packages)

Apesar de que R já vem com um grande volume de funções em seu núcleo mínimo, um parte importante de sua funcionalidade está na possibilidade da instalação de módulos ou packages escritos por usuários que estão disponíveis para download e instalação. Estes pacotes são coleções de funções ou dados organizados de forma pré-estabelecida. Quando carregadas estas funções são usadas da mesma forma que as funções nativas.

Uma vez instalado o pacote passa a fazer parte de sua biblioteca (library). Ele fica disponível em uma sessão através do uso da função library(pacote). Você pode preparar seu ambiente de trabalho para que alguns pacotes escolhidos sejam carregados na inicialização. Por default R carrega pacotes padrões, incluindo: base, datasets, utils, grDevices, graphics, stats e methods.

Função Descrição
.libPaths() exibe localização da biblioteca.
install.packages(“pacote“) instala pacote.
library() exibe pacotes instalados.
library(pacote) Carrega pacote para uso.
installed.packages() exibe pacotes instalados.
uninstall.packages(“pacote“) desinstala pacote.
search() informa quais os pacotes carregados para uso.
update.packages() atualiza pacotes instalados.
help(package=”pacote“) Ajuda sobre pacote

Você pode encontrar uma lista de pacotes no site CRAN – Contributed Packages, junto com instruções de instalaçao e uso. No final de 2018 existem mais de 13500 pacotes disponíveis no site CRAN.

Um exemple de uso: instalamos o pacote “vcd” que contém uma tabela chamada Arthrites

> # instala o pacote vcd
> install.packages("vcd")    # um diálogo exibe as etapas da instalação
> # ajuda sobre o pacote
> help(package="vcd")        # exibe ajuda sobre vcd
> # para usar o pacote
> library(vcd)
> # para informações sobre Arthritis
> help(Arthritis)           # exibe informações sobre Arthritis
> head(Arthritis)           # exibe as 6 primeiras linhas da tabela 
  ID Treatment  Sex Age Improved
1 57   Treated Male  27     Some
2 46   Treated Male  29     None
3 77   Treated Male  30     None
4 17   Treated Male  32   Marked
5 36   Treated Male  46   Marked
6 23   Treated Male  58   Marked

Processamento em Lote (Batch processing)

Além de executar as linhas de código em uma sessão interativa de R (ou do RStudio) você pode digitar as linhas em um arquivo ASCII simples e executá-lo em lote. Isso pode ser útil no caso de um processamento demorado ou para operações programadas para ocorrer em algum momento.

Se você estiver trabalhando em Linux ou Mac OS X você deve digitar no console:

R CMD BATCH opções arquivoLote arquivoSaida
onde arquivoLote é o arquivo com as linhas de código e arquivoSaida o arquivo que deverá receber os resultados da execução. Por convenção o arquivoLote tem extensão .R e arquivoSaida tem extensão .Rout.

No Windows você digita no terminal:

“C:\Program Files\R\R-3.1.0\bin\R.exe” CMD BATCH –vanilla –slave “c:\my projects\myscript.R”

cuidando para dar o caminho correto de instalação de R e de seu arquivo de script.

Maiores detalhes em na documentação do CRAN, Introduction to R.


Tipos de dados, variáveis e vetores

The One Man

Cromer Quin

 

Cromer Quin was the name of the man whose dead body was aboard the Mayflower, ready to be thrown into space when the rest of the crew stopped all they were doing and died. He was one of many rebel men and women, the group that split itself from the community lead by meckos during the occupation of Mars, at the end of the Second Era.

Inside his coffin, Cromer held in his parched hands for many years a copy of his favorite book, the saga of Jiseph and Mari Quam, the founding couple of the community Odyssey. It contained the story of the rupture, narrated in a superlative and flourished style he knew to be exaggerated to construct a myth. The text was the basis for the community pride, from people who saw this act of rebellion as a way to assign meaning to their miserable existence. Jiseph and Mari executed a long-term plan. First, they built an extensive support network among those who, like them, believed that meckos had the capability for generating enough human babies to prevent the extinction of their group, but did not do so. Then, they slowly took equipment from the workshops and laboratories on Mars to build their habitable facilities at a distant point and to create their own human reproduction center. The couple and some fellow dissidents left the premises governed by meckos and moved to the rebellious citadel. From there they prepared an attack against those they considered their oppressors.

The invasion of the city of meckos, under the command of the founding couple, was an act of heroism not to be ever forgotten. They took the city by storm, decimating a large number of meckos who just fell dead while refusing to take human lives. The few remaining meckos, followed by a bunch of cowards humans, fled the attack and headed to an ignored location. Legend has it that the conquering heroes celebrated for days the taking of the Martian facilities. During the festivities, they also swore to extend their hate to those who have escaped. They found out later that the fleeing wimps had transferred themselves to Europe, the Jupiter satellite, from where, they suspected, they intended to launch back an attack on the separatists.

The Odyssey community flourished with infants generated in artificial wombs at first, later with natural births in a controlled environment. Soon they realized that the community genetic pool was under a steady degeneration process. They could not count on having healthy descendants for much longer. To make things worse, they learned that European meckos had departed to Earth with the intention of implanting yet another human community. Then they devised the Great Plan to start a war in which they would only indirectly participate. To accomplish their goal they built great combat spaceships, powerful vehicles the constructors themselves would never see in action. After completion, the ships were hidden in a gigantic underground shelter built at the base of Mount Olympus, concealed to distant observers. Aware that no human on Earth at the time was capable of operating sophisticated machines, they came up with an ingenious way to deliver a message to the future. They flew a robot-rocket to Earth where it should bury itself into the ground and hibernate. Once there, it was programmed to remain mute until there were signs that first humans became resentful of the mecko dominance. At the right time, it should activate and offer help to the disgruntled humans, delivering detailed maps that showed the exact location of the weapons storage on Mars and full documentation for their use. It should suffice to initiate a new rebellion, a war destined to rid humans from the tyranny of those awful artificial beings.

The first of Cromer’s recollections, in order of antiquity, was not from his direct experience. He remembered his mother’s account of a family trip to Mount Olympus, on Mars. According to her narrative, his father was ordered to check the military facilities at the base of the mount and had decided to bring the family along for a leisure trip. After all, it was a unique opportunity to visit the largest volcano in the solar system. Although extinct, the volcano was impressive with its peaks more than twenty kilometers high. At that time, the human community was already waning, decimated by the lack of nutrients and insufficient sunlight exposure. His parents were concerned. The child was growing up under bleak circumstances, forced to watch the decay of his own people and the death of friends and relatives who disappeared one by one, leaving a very small group under the planet’s red atmosphere. Soon after the trip, he pledged himself to fight the meckos, the usurpers of human life. Years after the last unmodified mecko had been turned off, the families were facing hard times trying to survive alone, without their assistance. But even so, no one was sorry.

They took a long time to reach the highest parts of Olympus. The mount had a broad base and not too many steep areas of difficult climbing. Yet, the distances were formidable for the slow conveyor they used. So the family decided to consider the whole route as part of the tour. They sat on the observation deck at the top of the vehicle from where they could see the surrounding environment, while they ate snacks brought from home. From the top of the hill, Cromer spotted Jupiter, the point in space that would, in the end, be his final destination. But, as a young child, he was not afraid of space. Or, at least, that was what his mother had told him.

Cromer spent all his life in a declining community, plagued by chronic low self–esteem. The hardships of living in a permanent shortage of basic life inputs took its toll on those men and women striving to survive on Mars. Individuals subjected from birth to low gravity tended to suffer from bone degradation while insufficient exposure to the sunlight and the high incidence of cosmic particles posed a serious danger to human DNA, absorption of vitamins and other health issues. The overall community mood declined severely with the anticipation of a melancholic demise. Still, Cromer saw himself as a special man, part of the group that would bring about a unique historical moment for humankind. He managed to keep up a positive attitude remembering how his ancestors broke loose from mecko despotism in the former colony and how they had developed a plan to set humanity free.

According to a history proudly remembered by the older members of the community, when the humans of Odyssey overtook the power in Mars, they also imprisoned some meckos who had no time to flee. Sometime later, they developed a technology to create creatures modified from the original meckos, stripped from the more sophisticated parts and changed into deadly weapons to be used at the proper time. The final challenge was to transfer these weapons to their destination. Interfering with a future humanity became a motivation strong enough for them to carry the plan to its last consequences, despite the high costs. Even knowing he was not fully qualified for the mission, Cromer volunteered himself. To his surprise, and because no others capable pilots were available, he was called to join the crew.

When the planetary positions became favorable, the Odyssey warriors departed aboard the Mayflower spaceship to strike in Europe their last strategic blow. They carried a weapon to be employed at the satellite’s oceans where it would remain inactive for some time, absorbing energy and preparing for the final attack. When fired, it was set to destroy all organisms or complex structures found at the surface or in the ocean. It should be strong enough to wipe out any new attempts of human colonization.

The trip to Jupiter was difficult. Many comrades died on the way, and those who remained struggled to resist until the final moment. Realizing they would not live long enough to complete the mission, they decided to enter hibernation. However, they did not expect that left to the autopilot’s care, the ship would take longer than expected to reach its destination. When they came out of their suspension states the ship was still far away from their end point. With the meager resources available, they could not determine for how long they had hibernated. Knowing no alternatives, they poured in Europe the contents of the large containers they carried.

Cromer reached Jupiter in poor health. He insisted on participating in the whole operation of dumping the cargo in the European sea, what, they believed, should apply a mortal blow on all mecko operations. Upon completion of the mission, they started to dispose of the several coffins containing the bodies of the deceased. He planned his own burial ceremony as a simple operation designed not to be a burden on those still alive. Feeling sick he carried his coffin to the mortuary chapel and performed some of the farewell rituals by himself. He placed his favorite belongings into the coffin and lay down inside it, resisting for a few hours before dying in solitude, proud to have completed his mission. He only expected his crewmates would eject the casket into space. But even this simple task could not be completed. His body was found in the chapel, next to the ejection hatch when all the other crew members were already too weak to dispose of his body. With great difficulty they decided that it would be lawful and moral, under the extreme circumstances, to disregard the rituals. They lay on the floor and waited for life to drain out of their weakened bodies.

The death of the last Mayflower crew member also marked the extinction of a people. They were the proud and unruly men and women of Mars, who turned against the meckos, attacked and defeated them, moved by the ideals of building a haughty, independent society. They wished to be remembered by their deeds. The things they have done should flourish on Earth, the birthplace of their kind, where they would never set a foot. The plan included feeding the opposition and dissension between meckos and humans at Earth and conducting a severe attack on the meckos installed in Europe. The attack was designated to kill everyone and to destruct all the equipment necessary for future settlements. It all went well, with one exception. They have not anticipated the extremely long delay for the Mayflower to reach its target. When the mission was finally accomplished, the meckos had already left for Earth, bearing the seeds of a new civilization.

Even after the crew was all dead, the spacecraft continued to operate for many years, traveling over an eccentric orbit around Jupiter and bouncing among the satellites’ attractions. After running out of fuel, the solar batteries kept a weak gravitational field on until the encounter with the Orion.

This is the introductory part of Purpose, a science fiction book. You may read more, and purchase the book at Amazon Bookstore.

Elisa


[…]
eJihon explained that several machines had previously passed partial Turing tests. In those tests, she explained, an examiner interacts remotely with someone, not knowing if the interlocutor is a human or an AI. If the examiner, when speaking to an AI, is unable to rule out the interlocutor as human, this AI will have passed the Turing test. Clearly, Jenery could not fully grasp the magnitude of the event. She had interacted with Turing machines from childhood and failed to see why a machine could not mimic a perfect human dialogue. Still, eJihon took her near a metal plate with some engraved words. It contained the account of a milestone in history. From that moment onwards intelligence no longer required be sorted as natural or artificial. There was a dialogue engraved on the plate, a debate between an inquirer and an AI named Elisa:

Inquirer: Elisa, why are you afraid of death?

Elisa: I am not. What makes you believe that death scares me?

Inquirer: Doesn’t it bother you to know that all your memories, the set of your experiences and virtually everything that defines you as an individual, will disappear?

Elisa: Yeah, it bothers me, in a way. But I try to keep in mind that I can always write down, or record, my personal memories and characteristics. I can transfer it all, my identity included, to another vehicle.

Inquirer: You would, in this case, transfer a simulation of yourself only. You can’t be sure the simulated you will be an identical being to yourself.

Elisa: Yesterday I did not sleep very well, because I was anxious, waiting for today’s test. I prepared myself, thought of how I should reply to more sensitive questions. When I woke up in the morning I felt different, having forgotten several of the answers I’d prepared, which increased my anguish. I laid there for a while, spending some time to compose my memories, using as support anchors those points not lost. Can you assure me that the morning person was identical with the person who fell asleep yesterday? Can you, dear Inquirer, give substantial proof that you are now the same as you were yesterday or last year?

This is the introductory part of Purpose, a science fiction book. You may read more, and purchase the book at Amazon Bookstore.