Introduction to R Programming




Esse material é uma atualização e tradução dos materiais elaborados pelos alunos do Departamento de Genética da ESALQ/USP - Brasil. Acesse o conteúdo em portugues ministrado em outros eventos nesse site.

Sugerimos que, antes de iniciar a prática aqui descrita, siga este tutorial para instalação do R e do RStudio.

Familiarização com a interface do RStudio

Abrindo o RStudio você verá:

A interface é separada em quatro janelas com principais funções:

  • Edição de código
  • Ambiente de trabalho e histórico
  • Console
  • Arquivos, gráficos, pacotes e ajuda

Explore cada uma das janelas. São inúmeras funcionalidades para cada uma delas, veremos algumas delas no decorrer do curso.

Um primeiro script

A janela de edição de código (provavelmente localizada no canto superior esquerdo) será utilizada para escrever o seu código. Abra um novo script clicando no + no canto superior esquerdo e selecionando R script.

Vamos então iniciar os trabalhos com o tradicional Hello World. Digite no seu script:

cat("Hello world")
## Hello world

Agora, selecione a linha e aperte o botão Run ou utilize Ctrl + enter.

Ao fazer isso o seu código será processado na janela Console, onde aparecerá em azul (se você estiver com as cores padrão do R) o código escrito e, logo em seguida, o resultado desejado. A linha somente não será processada no console se houver o símbolo # na frente. Agora, experimente colocar # na frente do código escrito. Novamente, selecione a linha e aperte Run.

# cat("Hello world")

O símbolo # é utilizado para comentários no código. Esta é uma ótima prática de organização e ajuda a lembrar, posteriormente, o que você estava pensando quando escreveu o código. Também é essencial para que outras pessoas possam entendê-lo. Como no exemplo:

# Iniciando os trabalhos no R
cat("Hello world")
## Hello world

Importante: sempre que quiser realizar alguma alteração, edite o seu script e não diretamente no console, pois tudo o que neste é escrito, não terá como ser salvo!

Para salvar seu script, você pode utilizar a aba Files localizada (como padrão) no canto direito inferior. Você pode procurar uma localização de sua preferência, criar uma nova pasta com o nome CursoR.

Dica:

  • Evite colocar espaços e pontuações no nome das pastas e arquivos, isso pode dificultar o acesso via linha de comando no R. Por exemplo, ao invés de Curso R, optamos por CursoR.

Depois, basta clicar no disquete localizado no cabeçalho do RStudio ou com Ctrl + s e selecionar o diretório CursoR criado. Scripts em R são salvos com a extensão .R.

Estabelecendo diretório de trabalho

Outra boa prática no R é deixar o script no mesmo diretório onde estão seus dados brutos (arquivos de entrada no script) e os dados processados (gráficos, tabelas, etc). Para isso, vamos fazer com que o R identifique o mesmo diretório em que você salvou o script como diretório de trabalho. Assim, ele entenderá que é dali que os dados serão obtidos e é para lá que também irão os resultados.

Você pode fazer isso utilizando as facilidades do RStudio, basta localizar o diretório CursoR pela aba Files, clicar em More e depois “Set as Working Directory”. Repare que irá aparecer no console algo como:

setwd("~/Documents/CursoR")

Ou seja, você pode utilizar este mesmo comando para realizar esta ação. O resultado será nossa pasta de trabalho. Quando estiver perdido/a ou para ter certeza que o diretório de trabalho foi alterado utilize:

getwd()

Facilitando a vida com Tab

Agora, imagine que você tem um diretório como ~/Documentos/mestrado/semestre1/disciplina_tal/aula_tal/dados_28174/analise_276182/resultados_161/. Não é fácil lembrar todo este caminho para escrever num comando setwd().

Além da facilidade da janela do RStudio, você também pode utilizar a tecla Tab para completar o caminho para você. Experimente buscando alguma pasta no seu computador. Basta começar a digitar o caminho e apertar Tab, ele irá completar o nome para você! Se você tiver mais do que um arquivo com aquele início de nome, aperte duas vezes o Tab, ele mostrará todas as opções.

O Tab funciona não só para indicar caminhos, mas também para comandos e nomes de objetos. É muito comum cometermos erros de digitação no código. Utilizar o Tab reduzirá significativamente esses erros.

O Tab pode ser ainda mais poderoso se você tiver acesso à ferramenta GitHub Copilot. Com ela, você pode utilizar o Tab para completar o código que você está escrevendo. É uma ferramenta baseada em inteligência artificial que sugere o código que você está escrevendo. É uma ferramenta paga, mas você pode utilizar gratuitamente por 60 dias.

Operações básicas

Vamos então à linguagem!

O R pode funcionar como uma simples calculadora, que utiliza a mesma sintaxe que outros programas (como o excel):

1+1.3                 #Decimal definido com "."
2*3
2^3
4/2

sqrt(4)              #raíz quadrada
log(100, base = 10)  #Logaritmo na base 10
log(100)             #Logaritmo com base neperiana

Agora, utilize as operações básicas para solucionar expressão abaixo. Lembre-se de utilizar parênteses () para estabelecer prioridades nas operações.

\((\frac{13+2+1.5}{3})+ log_{4}96\)

Resultado esperado:

## [1] 8.792481

Repare que, se posicionar o parênteses de forma incorreta, o código não resultará em nenhuma mensagem de erro, pois este é um erro que chamamos de erro lógico ou erro silencioso, ou seja, o código roda, mas não faz o que você gostaria que ele fizesse. Esse é o tipo de erro mais perigoso e difícil de ser consertado. Veja um exemplo:

13+2+1.5/3 + log(96, base = 4)
## [1] 18.79248

Os erros que produzem uma mensagem, seja um aviso (warning) ou um erro (error) são chamados de erros de sintaxe. Nesses casos, o R retornará uma mensagem para te ajudar a corrigí-los. Os warnings não comprometem o funcionamento do código, mas chamam a atenção para algum ponto; já os errors precisam necessariamente ser corrigidos para que o código rode.

Exemplo de error:

((13+2+1,5)/3) + log(96, base = 4)

Você pode também esquecer de fechar algum parênteses, ou aspas, ou colchetes, ou chaves, nesses casos, o R ficará aguardando o comando para fechar o bloco de código sinalizando com um +:

((13+2+1.5)/3 + log(96, base = 4)

Se acontecer, vá até o console e aperte ESC, que o bloco será finalizado para que você possa corrigí-lo.

Os comandos log e sqrt são duas de muitas outras funções básicas que o R possui. Funções são conjuntos de instruções organizadas para realizar uma tarefa. Para todas elas, o R possui uma descrição para auxiliar no seu uso. Para acessar essa ajuda use:

?log

E será aberta a descrição da função na janela Help do RStudio.

Se a descrição do próprio R não for suficiente para você entender como funciona a função, busque no google (de preferência em inglês). Existem diversos sites e fóruns com informações didáticas das funções do R.

Operações com vetores

Os vetores são as estruturas mais simples trabalhadas no R. Construímos um vetor com uma sequencia numérica usando:

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

MUITA ATENÇÃO: O c é a função do R (Combine Values into a Vector or List) com a qual construímos um vetor!

Utilizamos o simbolo : para criar sequências de números inteiros, como:

1:10
##  [1]  1  2  3  4  5  6  7  8  9 10

Podemos utilizar outras funções para gerar sequências, como:

seq(from=0, to=100, by=5)
##  [1]   0   5  10  15  20  25  30  35  40  45  50  55  60  65  70  75  80  85  90
## [20]  95 100
# ou
seq(0,100,5) # Se você já souber a ordem dos argumentos da função
##  [1]   0   5  10  15  20  25  30  35  40  45  50  55  60  65  70  75  80  85  90
## [20]  95 100
  • Crie uma sequencia utilizando a função seq que varie de 4 a 30, com intervalos de 3 em 3.
## [1]  4  7 10 13 16 19 22 25 28

A função rep gera sequências com números repetidos:

rep(3:5, 2)
## [1] 3 4 5 3 4 5

Podemos realizar operações utilizando esses vetores:

c(1,4,3,2)*2
c(4,2,1,5)+c(5,2,6,1)
c(4,2,1,5)*c(5,2,6,1)

Repare que já esta ficando cansativo digitar os mesmos números repetidamente, vamos resolver isso criando objetos para armazenar nossos vetores e muito mais.

Criando objetos

O armazenamento de informações em objetos e a possível manipulação desses faz do R uma linguagem orientada por objetos. Para criar um objeto basta atribuir valores para as variáveis, como a seguir:

x = c(30.1,30.4,40,30.2,30.6,40.1)
# ou
x <- c(30.1,30.4,40,30.2,30.6,40.1)

y = c(0.26,0.3,0.36,0.24,0.27,0.35)

Os mais antigos costumam usar o sinal <-, mas tem a mesma função de =. Há quem prefira usar o <- como atribuição em objetos e = apenas para definir os argumentos dentro de funções. Organize-se da forma como preferir.

Para acessar os valores dentro do objeto basta:

x
## [1] 30.1 30.4 40.0 30.2 30.6 40.1

A linguagem é sensível à letras maiúsculas e minúsculas. Logo, x é diferente de X:

X

O objeto X não foi criado.

O nome dos objetos é uma escolha pessoal, a sugestão é tentar manter um padrão para melhor organização. Aqui estão alguma dicas:

  • Usar nomes descritivos
  • Evitar começar com números
  • Não usar espaços (usar _ ou camelCase)
  • Não usar caracteres especiais
  • Manter consistência no padrão escolhido
  • Evitar nomes muito longos
  • Não usar acentos ou caracteres não-ASCII

Alguns nomes não podem ser usados por estabelecerem papéis fixos no R, são eles:

  • TRUE - Verdadeiro, valor lógico
  • FALSE - Falso, valor lógico
  • if, else, for, while, break, next - Palavras reservadas para estruturas condicionais e de repetição
  • for, while, repeat - Palavras reservadas para estruturas de repetição
  • function - Palavra reservada para definição de funções
  • in, NA, NaN, NULL - Palavras reservadas para valores especiais
  • NA_integer_, NA_real, NA_character_, NA_complex_ - Valores especiais para representar dados ausentes

Podemos então realizar as operações com o objeto criado:

x+2
## [1] 32.1 32.4 42.0 32.2 32.6 42.1
x*2
## [1] 60.2 60.8 80.0 60.4 61.2 80.2

Para realizar a operação o R alinha os dois vetores e realiza a operação elemento à elemento. Observe:

x + y
## [1] 30.36 30.70 40.36 30.44 30.87 40.45
x*y
## [1]  7.826  9.120 14.400  7.248  8.262 14.035

Se os vetores tiverem tamanhos diferentes, ele irá repetir o menor para realizar a operação elemento a elemento com todos do maior.

x*2
x*c(1,2)

Se caso o menor vetor não for múltiplo do maior, obteremos um aviso:

x*c(1,2,3,4)
## Warning in x * c(1, 2, 3, 4): longer object length is not a multiple of shorter
## object length
## [1]  30.1  60.8 120.0 120.8  30.6  80.2

Repare que o warning não compromente o funcionamento do código, ele só dá uma dica de que algo pode não estar da forma como você gostaria.

Podemos também armazenar a operação em outro objeto:

z <- (x+y)/2
z

Podemos também aplicar algumas funções, como exemplo:

sum(z)  # soma dos valores de z
## [1] 101.59
mean(z) # média 
## [1] 16.93167
var(z)  # variância
## [1] 6.427507

Indexação

Acessamos somente o 3º valor do vetor criado com []:

z[3]

Também podemos acessar o número da posição 2 a 4 com:

z[2:4]
## [1] 15.35 20.18 15.22

Para obter informações do vetor criado utilize:

str(z)
##  num [1:6] 15.2 15.3 20.2 15.2 15.4 ...

A função str nos diz sobre a estrutura do vetor, que se trata de um vetor numérico com 6 elementos.

Os vetores também podem receber outras categorias como caracteres:

clone <- c("GRA02", "URO01", "URO03", "GRA02", "GRA01", "URO01")

Outra classe são os fatores, esses podem ser um pouco complexos de lidar.

De forma geral, fatores são valores categorizados por levels, como exemplo, se transformarmos nosso vetor de caracteres clone em fator, serão atribuidos níveis para cada uma das palavras:

clone_fator <- as.factor(clone)
str(clone_fator)
##  Factor w/ 4 levels "GRA01","GRA02",..: 2 3 4 2 1 3
levels(clone_fator)
## [1] "GRA01" "GRA02" "URO01" "URO03"

Dessa forma, teremos apenas 4 níveis para um vetor com 6 elementos, já que as palavras “GRA02” e “URO01” se repetem. Podemos obter o número de elementos do vetor ou o seu comprimento com:

length(clone_fator)
## [1] 6

Também há vetores lógicos, que recebem valores de verdadeiro ou falso:

logico <- x > 40
logico   # Os elementos são maiores que 40?
## [1] FALSE FALSE FALSE FALSE FALSE  TRUE

Com ele podemos, por exemplo, identificar quais são as posições dos elementos maiores que 40:

which(logico)  # Obtendo as posiçoes dos elementos TRUE
## [1] 6
x[which(logico)] # Obtendo os números maiores que 40 do vetor x pela posição
## [1] 40.1
# ou
x[which(x > 40)]
## [1] 40.1

Também podemos localizar elementos específicos com:

clone %in% c("URO03", "GRA02")
## [1]  TRUE FALSE  TRUE  TRUE FALSE FALSE

Também podem ser úteis as funções any e all. Pesquise sobre elas.

Encontre mais sobre outros operadores lógicos, como o > utilizado, neste link.

Warning1

Faça uma sequência numérica, contendo 10 valores inteiros, e salve em um objeto chamado “a”.

(a <- 1:10)
##  [1]  1  2  3  4  5  6  7  8  9 10

Crie outra sequência, utilizando números decimais e qualquer operação matemática, de tal forma que seus valores sejam idênticos ao objeto “a”.

b <- seq(from = 0.1, to = 1, 0.1)
(b <- b*10)
##  [1]  1  2  3  4  5  6  7  8  9 10

Os dois vetores parecem iguais, não?

Então, utilizando um operador lógico, vamos verificar o objeto “b” é igual ao objeto “a”.

a==b
##  [1]  TRUE  TRUE FALSE  TRUE  TRUE  TRUE FALSE  TRUE  TRUE  TRUE

Alguns valores não são iguais. Como isso é possivel?

a==round(b)
##  [1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE

Warning2

Não é possível misturar diferentes classes dentro de um mesmo vetor. Ao tentar fazer isso, repare que o R irá tentar igualar para uma única classe:

errado <- c(TRUE, "vish", 1)
errado
## [1] "TRUE" "vish" "1"

No caso, todos os elementos foram transformados em caracteres.

Algumas Dicas:

  • Cuidado com a prioridade das operações, na dúvida, sempre acrescente parenteses conforme seu interesse de prioridade.
  • Lembre-se que, se esquecer de fechar algum ( ou [ ou ", o console do R ficará esperando você fechar indicando um +. Nada será processado até que você digite diretamente no console um ) ou aperte ESC.
  • Cuidado para não sobrepor objetos já criados criando outros com o mesmo nome. Use, por exemplo: altura1, altura2.
  • Mantenha no seu script .R somente os comandos que funcionaram e, de preferência, adicione comentários. Você pode, por exemplo, comentar dificuldades encontradas, para que você não cometa os mesmos erros mais tarde.

Se estiver adiantada/o em relação aos colegas, você já pode fazer os exercícios da Sessão 1, se não, faça-os em outro momento e nos envie dúvidas.

Matrizes

As matrizes são outra classe de objetos muito utilizadas no R, com elas podemos realizar operações de maior escala de forma automatizada.

Por serem usadas em operações, normalmente armazenamos nelas elementos numéricos. Para criar uma matriz, determinamos uma sequência de números e indicamos o número de linhas e colunas da matriz:

X <- matrix(1:12, nrow = 6, ncol = 2)
X
##      [,1] [,2]
## [1,]    1    7
## [2,]    2    8
## [3,]    3    9
## [4,]    4   10
## [5,]    5   11
## [6,]    6   12

Podemos também utilizar sequências já armazenadas em vetores para gerar uma matriz, desde que eles sejam numéricos:

W <- matrix(c(x,y), nrow = 6, ncol =2)
W
##      [,1] [,2]
## [1,] 30.1 0.26
## [2,] 30.4 0.30
## [3,] 40.0 0.36
## [4,] 30.2 0.24
## [5,] 30.6 0.27
## [6,] 40.1 0.35

Com elas podemos realizar operações matriciais:

X*2
##      [,1] [,2]
## [1,]    2   14
## [2,]    4   16
## [3,]    6   18
## [4,]    8   20
## [5,]   10   22
## [6,]   12   24
X*X        
##      [,1] [,2]
## [1,]    1   49
## [2,]    4   64
## [3,]    9   81
## [4,]   16  100
## [5,]   25  121
## [6,]   36  144
X%*%t(X)          # Multiplicação matricial
##      [,1] [,2] [,3] [,4] [,5] [,6]
## [1,]   50   58   66   74   82   90
## [2,]   58   68   78   88   98  108
## [3,]   66   78   90  102  114  126
## [4,]   74   88  102  116  130  144
## [5,]   82   98  114  130  146  162
## [6,]   90  108  126  144  162  180

Utilizar essas operações exige conhecimento de álgebra de matrizes, se quiser se aprofundar a respeito, o livro Linear Models in Statistics, Rencher (2008) possui um boa revisão à respeito. Você também pode explorar a sintaxe do R para essas operações neste link.

Acessamos os números internos à matriz dando as coordenadas [linha,coluna], como no exemplo:

W[4,2] # Número posicionado na linha 4 e coluna 2
## [1] 0.24

As vezes pode ser informativo dar nomes às colunas e às linhas da matriz, fazemos isso com:

colnames(W) <- c("altura", "diametro")
rownames(W) <- clone
W
##       altura diametro
## GRA02   30.1     0.26
## URO01   30.4     0.30
## URO03   40.0     0.36
## GRA02   30.2     0.24
## GRA01   30.6     0.27
## URO01   40.1     0.35

Essas funções colnames e rownames também funcionam nos data.frames.

Data.frames

Diferente das matrizes, não realizamos operações com os data.frames, mas eles permitem a união de vetores com classes diferentes. Os data frames são semelhantes a tabelas geradas em outros programas, como o excel.

Os data frames são combinações de vetores de mesmo comprimento. Todos os que criamos até agora tem tamanho 6, verifique.

Podemos assim combiná-los em colunas de um único data.frame:

campo1 <- data.frame("clone" = clone,     # Antes do sinal de "="  
                     "altura" = x,        # estabelecemos os nomes  
                     "diametro" = y,      # das colunas
                     "idade" = rep(3:5, 2),
                     "corte"= logico) 
campo1
##   clone altura diametro idade corte
## 1 GRA02   30.1     0.26     3 FALSE
## 2 URO01   30.4     0.30     4 FALSE
## 3 URO03   40.0     0.36     5 FALSE
## 4 GRA02   30.2     0.24     3 FALSE
## 5 GRA01   30.6     0.27     4 FALSE
## 6 URO01   40.1     0.35     5  TRUE

Podemos acessar cada uma das colunas com:

campo1$idade
## [1] 3 4 5 3 4 5

Ou também com:

campo1[,4] 
## [1] 3 4 5 3 4 5

Aqui, o número dentro dos colchetes se refere à coluna, por ser o segundo elemento (separado por vírgula). O primeiro elemento se refere à linha. Como deixamos o primeiro elemento vazio, estaremos nos referindo a todas as linhas para aquela coluna.

Dessa forma, se quisermos obter um conteúdo específico podemos dar as coordenadas com [linha,coluna]:

campo1[1,2] 
## [1] 30.1
  • Obtenha o diâmetro do clone “URO03”.
## [1] 0.36

Mesmo se tratando de um data frame, podemos realizar operações com os vetores numéricos que a compõe.

  • Com o diâmetro e a altura das árvores, calcule o volume conforme a fórmula a seguir e armazene em um objeto volume:

\(3.14*(diametro/2)^2*altura\)

## [1] 1.597287 2.147760 4.069440 1.365523 1.751131 3.856116

Agora, vamos adicionar o vetor calculado com o volume ao nosso data frame. Para isso use a função cbind.

campo1 <- cbind(campo1, volume)
campo1
##   clone altura diametro idade corte   volume
## 1 GRA02   30.1     0.26     3 FALSE 1.597287
## 2 URO01   30.4     0.30     4 FALSE 2.147760
## 3 URO03   40.0     0.36     5 FALSE 4.069440
## 4 GRA02   30.2     0.24     3 FALSE 1.365523
## 5 GRA01   30.6     0.27     4 FALSE 1.751131
## 6 URO01   40.1     0.35     5  TRUE 3.856116
str(campo1)
## 'data.frame':    6 obs. of  6 variables:
##  $ clone   : chr  "GRA02" "URO01" "URO03" "GRA02" ...
##  $ altura  : num  30.1 30.4 40 30.2 30.6 40.1
##  $ diametro: num  0.26 0.3 0.36 0.24 0.27 0.35
##  $ idade   : int  3 4 5 3 4 5
##  $ corte   : logi  FALSE FALSE FALSE FALSE FALSE TRUE
##  $ volume  : num  1.6 2.15 4.07 1.37 1.75 ...

Algumas dicas:

  • Lembre-se que, para construir matrizes e data frames, as colunas devem apresentar o mesmo número de elementos.

  • Caso não saiba o operador ou a função que deve ser utilizada, busque no google ou pergunte para o chatgpt ou qualquer outra ferramenta. Por exemplo, se está em dúvida em como calcular o desvio padrão, busque por “desvio padrão R” ou, melhor ainda, “standard deviation R”. A comunidade do R é bastante ativa e grande parte das suas perguntas sobre ele já foram respondidas em algum lugar da web.

  • Não esqueça que tudo o que fizer no R precisa ser explicitamente indicado, como uma multiplicação 4ac com 4*a*c. Para gerar um vetor 1,3,2,6 é necessário: c(1,3,2,6).

Listas

Listas consistem em uma coleção de objetos, não necessariamente de mesma classe. Nelas podemos armazenar todos os outros objetos já vistos e recuperá-los pela indexação com [[. Como exemplo, vamos utilizar alguns objetos que já foram gerados.

minha_lista <- list(campo1 = campo1, media_alt = tapply(campo1$altura, campo1$idade, mean), matrix_ex = W)
str(minha_lista)
## List of 3
##  $ campo1   :'data.frame':   6 obs. of  6 variables:
##   ..$ clone   : chr [1:6] "GRA02" "URO01" "URO03" "GRA02" ...
##   ..$ altura  : num [1:6] 30.1 30.4 40 30.2 30.6 40.1
##   ..$ diametro: num [1:6] 0.26 0.3 0.36 0.24 0.27 0.35
##   ..$ idade   : int [1:6] 3 4 5 3 4 5
##   ..$ corte   : logi [1:6] FALSE FALSE FALSE FALSE FALSE TRUE
##   ..$ volume  : num [1:6] 1.6 2.15 4.07 1.37 1.75 ...
##  $ media_alt: num [1:3(1d)] 30.1 30.5 40
##   ..- attr(*, "dimnames")=List of 1
##   .. ..$ : chr [1:3] "3" "4" "5"
##  $ matrix_ex: num [1:6, 1:2] 30.1 30.4 40 30.2 30.6 40.1 0.26 0.3 0.36 0.24 ...
##   ..- attr(*, "dimnames")=List of 2
##   .. ..$ : chr [1:6] "GRA02" "URO01" "URO03" "GRA02" ...
##   .. ..$ : chr [1:2] "altura" "diametro"

Quero acessar o data.frame campo1

minha_lista[[1]] 
##   clone altura diametro idade corte   volume
## 1 GRA02   30.1     0.26     3 FALSE 1.597287
## 2 URO01   30.4     0.30     4 FALSE 2.147760
## 3 URO03   40.0     0.36     5 FALSE 4.069440
## 4 GRA02   30.2     0.24     3 FALSE 1.365523
## 5 GRA01   30.6     0.27     4 FALSE 1.751131
## 6 URO01   40.1     0.35     5  TRUE 3.856116
# ou
minha_lista$campo1
##   clone altura diametro idade corte   volume
## 1 GRA02   30.1     0.26     3 FALSE 1.597287
## 2 URO01   30.4     0.30     4 FALSE 2.147760
## 3 URO03   40.0     0.36     5 FALSE 4.069440
## 4 GRA02   30.2     0.24     3 FALSE 1.365523
## 5 GRA01   30.6     0.27     4 FALSE 1.751131
## 6 URO01   40.1     0.35     5  TRUE 3.856116

Para acessar uma coluna específica no data.frame campo1, que está dentro da minha_lista:

minha_lista[[1]][[3]]
## [1] 0.26 0.30 0.36 0.24 0.27 0.35
# ou
minha_lista[[1]]$diametro
## [1] 0.26 0.30 0.36 0.24 0.27 0.35
# ou
minha_lista$campo1$diametro
## [1] 0.26 0.30 0.36 0.24 0.27 0.35

Listas são muito úteis, por exemplo, quando vamos utilizar/gerar diversos objetos dentro de um loop.

Arrays

Este é um tipo de objeto que você provavelmente não irá utilizar agora no início, mas é bom saber da sua existência. São utilizados para armazenar dados com mais de duas dimensões. Por exemplo, se criarmos um array:

(meu_array <- array(1:24, dim = c(2,3,4)))
## , , 1
## 
##      [,1] [,2] [,3]
## [1,]    1    3    5
## [2,]    2    4    6
## 
## , , 2
## 
##      [,1] [,2] [,3]
## [1,]    7    9   11
## [2,]    8   10   12
## 
## , , 3
## 
##      [,1] [,2] [,3]
## [1,]   13   15   17
## [2,]   14   16   18
## 
## , , 4
## 
##      [,1] [,2] [,3]
## [1,]   19   21   23
## [2,]   20   22   24

Teremos quatro matrizes com duas linhas e três colunas e os números de 1 a 24 estarão distribuídos nelas por colunas.

Se estiver adiantada/o em relação aos colegas, você já pode fazer os exercícios da Sessão 2, se não, faça-os em outro momento e nos envie dúvidas pelo fórum.

Importando e exportando dados

Faça o download dos objetos criados até agora clicando aqui

Os arquivos RData são exclusivos do R, clicando duas vezes no arquivo ou utilizando:

load("data/dia_1.RData")

Você vai recuperar todos os objetos gerados até agora no tutorial.

Se tiver com acesso à internet. Você também pode usar o link web diretamente:

load(url("https://breeding-insight.github.io/learn-hub/r-intro/data/dia_1.RData"))

Para gerar esse arquivo RData, eu rodei todos os códigos daqui para cima e usei:

save.image(file = "data/dia_1.RData")

Este comando salva tudo o que você tem no seu Ambiente Global (todos os objetos que aparecem ali no canto direito superior). Você pode também salvar somente um objeto com:

save(campo1, file = "data/campo1.RData")

Se removermos ele do nosso Ambiente Global com:

rm(campo1)  # Certifique-se que salvou o arquivo RData antes de removê-lo

Podemos facilmente obtê-lo novamente com:

load("data/campo1.RData")

O formato RData é exclusivo para o R, ele é interessante de ser usado para fazer o que estamos fazendo, paramos a análise em um dia, vamos continuar em um outro e não queremos ter que rodar tudo de novo. Mas muitas vezes precisamos exportar nossos dados para outros programas, que exigem outros formatos, como, por exemplo, .txt ou .csv. Para isso utilizamos:

write.table(campo1, file = "campo1.txt", sep = ";", dec = ".", row.names = FALSE)
write.csv(campo1, file = "campo1.csv", row.names = TRUE)

Obs: Você pode adquirir pacotes para exportar e importar dados com outros formatos, como exemplo o pacote openxlsx exporta e importa dados com formato do excel. O pacote vroom pode ser utilizado para compactar grandes tabelas. Para instalar pacotes, utilize a função install.packages("nome_do_pacote") e para carregar o pacote utilize library(nome_do_pacote).Veremos mais sobre pacotes na sessão “Aplicação de Pacotes” deste curso.

# install.packages("openxlsx")
library(openxlsx)

write.xlsx(campo1, file = "campo1.xlsx")

Ao exportar, há diversas opções para a formatação do arquivo, é importante considerá-las se o arquivo for usado em outro software posteriormente.

Abra os arquivos gerados no seu bloco de notas para visualizar sua formatação. Repare que o arquivo .txt foi salvo com o separador ; e o separador decimal .. Já o arquivo .csv foi salvo com o separador de vírgula , e o separador decimal ..

Esses arquivos podem ser lidos novamente pelo R, utilizando as funções e suas especificações:

campo1_txt <- read.table(file = "campo1.txt", sep=";", dec=".", header = TRUE)
campo1_csv <- read.csv(file = "campo1.csv")
campo1_xlsx <- read.xlsx("campo1.xlsx", sheet = 1)
head(campo1_txt)
head(campo1_csv)
head(campo1_xlsx)

Agora que aprendemos a importar dados, vamos trabalhar com o conjunto gerado a partir do formulário enviado para vocês e para alunos de outras versões desse curso.

A planilha com os dados está disponível no link abaixo, adicione-a ao seu diretório de trabalho ou indique o caminho da pasta ao importá-la para dentro do R, como a seguir.

Também podemos importar os dados diretamente do github, apontando o endereço web.

dados <- read.csv("https://breeding-insight.github.io/learn-hub/r-intro/data/dados_2025.csv")

Aqui usaremos também o argumento na.strings que irá indicar como foram nomeados os dados perdidos.

dados <- read.csv(file = "data/dados_2025.csv", na.strings="-", header = T, dec = ",")
head(dados)
load("data/dados_2025.RData")

Vamos explorar a estrutura dos dados coletados:

str(dados)
## 'data.frame':    124 obs. of  8 variables:
##  $ Timestamp                                                                                   : chr  "07/04/2025 14:00:00" "07/04/2025 14:00:00" "07/04/2025 14:00:00" "07/04/2025 14:00:00" ...
##  $ Affiliation                                                                                 : chr  "Rcourse2021" "Rcourse2021" "Rcourse2021" "Rcourse2021" ...
##  $ Using.Google.Maps..please.provide.the.longitude.of.the.city.country.of.your.birth.          : chr  "-54.5724" "-47.6476" "-48.0547" "-106.6563" ...
##  $ Using.Google.Maps..please.provide.the.latitude.of.the.city.country.of.your.birth.           : chr  "-25.5263" "-22.725" "-15.911" "52.1418" ...
##  $ Background.Field..e.g..Molecular.Biology..Animal.Breeding..Genetics..etc..                  : chr  "Agronomia" "Agronomia" "Biotecnologia" "Licenciatura em Ciências Biológicas" ...
##  $ Current.professional.affiliation                                                            : chr  "PhD" "PhD" "Masters degree" "Other" ...
##  $ If.you.chose.other.in.the..current.professional.affiliation..question.above..please.specify.: chr  NA NA NA NA ...
##  $ Level.of.R.knowledge                                                                        : chr  "Intermediate" "Intermediate" "Beginner (some knowledge)" "Intermediate" ...
# também
dim(dados)
## [1] 124   8

Repare que nos nomes das colunas ainda estão as perguntas completas feitas no formulário, vamos alterar para nomes mais fáceis de trabalhar:

colnames(dados)
## [1] "Timestamp"                                                                                   
## [2] "Affiliation"                                                                                 
## [3] "Using.Google.Maps..please.provide.the.longitude.of.the.city.country.of.your.birth."          
## [4] "Using.Google.Maps..please.provide.the.latitude.of.the.city.country.of.your.birth."           
## [5] "Background.Field..e.g..Molecular.Biology..Animal.Breeding..Genetics..etc.."                  
## [6] "Current.professional.affiliation"                                                            
## [7] "If.you.chose.other.in.the..current.professional.affiliation..question.above..please.specify."
## [8] "Level.of.R.knowledge"
colnames(dados) = c("Data", "Afiliação", "Longitude", "Latitude", "Background", "Presente_Ocupação", "Explique", "ConhecimentoR")
colnames(dados)
## [1] "Data"              "Afiliação"         "Longitude"        
## [4] "Latitude"          "Background"        "Presente_Ocupação"
## [7] "Explique"          "ConhecimentoR"
str(dados)
## 'data.frame':    124 obs. of  8 variables:
##  $ Data             : chr  "07/04/2025 14:00:00" "07/04/2025 14:00:00" "07/04/2025 14:00:00" "07/04/2025 14:00:00" ...
##  $ Afiliação        : chr  "Rcourse2021" "Rcourse2021" "Rcourse2021" "Rcourse2021" ...
##  $ Longitude        : chr  "-54.5724" "-47.6476" "-48.0547" "-106.6563" ...
##  $ Latitude         : chr  "-25.5263" "-22.725" "-15.911" "52.1418" ...
##  $ Background       : chr  "Agronomia" "Agronomia" "Biotecnologia" "Licenciatura em Ciências Biológicas" ...
##  $ Presente_Ocupação: chr  "PhD" "PhD" "Masters degree" "Other" ...
##  $ Explique         : chr  NA NA NA NA ...
##  $ ConhecimentoR    : chr  "Intermediate" "Intermediate" "Beginner (some knowledge)" "Intermediate" ...

Agora usaremos os dados que temos para aprender diferentes comandos e funções do Ambiente R.

Primeiro, vamos verificar quantos alunos responderam as questões do formulario da disciplina, contando o número de linhas, para isso use a função nrow.

nrow(dados)
## [1] 124

Vamos então verificar se temos no nosso grupo pessoas que compartilham a mesma graduação e ocupação.

Podemos verificar isso facilmente com a função table, que indica a frequência de cada observação:

table(dados$Afiliação)
table(dados$Presente_Ocupação)

Estruturas condicionais

if e else

Para nossa próxima atividade com os dados, vamos primeiro entender como funcionam as estruturas if e else.

Nas funções condicionais if e else, estabelecemos uma condição para if, se ela for verdade a atividade será realizada, caso contrário (else) outra tarefa será. Como no exemplo:

if(2 >3){
  cat("dois é maior que três")
} else {
  cat("dois não é maior que três")
}
## dois não é maior que três
  • Descubra a Nivel de Conhecimentos em R da segunda pessoa que o respondeu (linha 2). Envie uma mensagem “Nível Intermediario” se for intermediario ou “Nível Básico ou avançado” caso contrario. (dica: o sinal == se refere a “exatamente igual a”)
head(dados)
##                  Data   Afiliação Longitude Latitude
## 1 07/04/2025 14:00:00 Rcourse2021  -54.5724 -25.5263
## 2 07/04/2025 14:00:00 Rcourse2021  -47.6476  -22.725
## 3 07/04/2025 14:00:00 Rcourse2021  -48.0547  -15.911
## 4 07/04/2025 14:00:00 Rcourse2021 -106.6563  52.1418
## 5 07/04/2025 14:00:00 Rcourse2021  -47.6604 -22.7641
## 6 07/04/2025 14:00:00 Rcourse2021  -47.6434 -22.7118
##                            Background Presente_Ocupação Explique
## 1                           Agronomia               PhD     <NA>
## 2                           Agronomia               PhD     <NA>
## 3                       Biotecnologia    Masters degree     <NA>
## 4 Licenciatura em Ciências Biológicas             Other     <NA>
## 5                           Agronomia      Profissional     <NA>
## 6                           Agronomia               PhD     <NA>
##               ConhecimentoR
## 1              Intermediate
## 2              Intermediate
## 3 Beginner (some knowledge)
## 4              Intermediate
## 5 Beginner (some knowledge)
## 6              Intermediate
if(dados$ConhecimentoR[2] =="Intermediate"){
  cat("Nível Intermediário")
} else {
  cat("Nível Básico ou Avançado")
}
## Nível Intermediário

Podemos espeficiar mais do que uma condição repetindo a estrutura if else: Agora vamos estudar a ocupação das pessoas que responderam ao questionário.

if(dados$Presente_Ocupação[2] == "Other"){
  print(dados$Explique[2])
} else if (dados$Presente_Ocupação[2] == "PhD"){
  print(paste("O seu doutorado é em:",dados$Background[2], "?"))
} else {
  print(paste("Você ainda trabalha com:", dados$Background[2], "?"))
}
## [1] "O seu doutorado é em: Agronomia ?"

Mas repare que só é possível utilizar essas estruturas para um elemento individual do vetor ou em todo ele, se quisermos percorrer os elementos individualmente precisamos recorrer a outro recurso.

Estruturas de repetição

For

Esse recurso pode ser a função for, uma função muito utilizada e poderosa. Ela constitui uma estrutura de loop, pois irá aplicar a mesma atividade repetidamente até atingir uma determinada condição. Veja exemplos:

for(i in 1:10){
  print(i)
}
## [1] 1
## [1] 2
## [1] 3
## [1] 4
## [1] 5
## [1] 6
## [1] 7
## [1] 8
## [1] 9
## [1] 10
test <- vector()
for(i in 1:10){
  test[i] <- i+4 
}
test
##  [1]  5  6  7  8  9 10 11 12 13 14

Nos casos acima, i funciona como um índice que irá variar de 1 até 10 a operação determinada entre chaves.

Com essa estrutura, podemos repetir a operação realizada com as estruturas if e else para todo o vetor:

for(i in 1:nrow(dados)){
  if(dados$Presente_Ocupação[i] == "Other"){
    print(dados$Explique[i])
  } else if (dados$Presente_Ocupação[i] == "PhD"){
    print(paste("O seu doutorado é em:",dados$Background[i], "?"))
  } else {
    print(paste("Você ainda trabalha com:", dados$Background[i], "?"))
  }
}

Repare que algumas pessoas não responderam quando perguntadas o que queriam dizer com “outro”. Para evitar que o R retorne um erro, podemos usar a função is.na para verificar se a resposta é NA (não disponível).

for(i in 1:nrow(dados)){
  if(dados$Presente_Ocupação[i] == "Other"){
    if(is.na(dados$Explique[i])) {
      print("Esta pessoa não explicou o que quis dizer com 'outro'") 
      } else {
        print(dados$Explique[i])
      }
  } else if (dados$Presente_Ocupação[i] == "PhD"){
    print(paste("O seu doutorado é em:",dados$Background[i], "?"))
  } else {
    print(paste("Você ainda trabalha com:", dados$Background[i], "?"))
  }
}
## [1] "O seu doutorado é em: Agronomia ?"
## [1] "O seu doutorado é em: Agronomia ?"
## [1] "Você ainda trabalha com: Biotecnologia ?"
## [1] "Esta pessoa não explicou o que quis dizer com 'outro'"
## [1] "Você ainda trabalha com: Agronomia ?"
## [1] "O seu doutorado é em: Agronomia ?"
## [1] "O seu doutorado é em: Zootecnia ?"
## [1] "O seu doutorado é em: Agronomia ?"
## [1] "O seu doutorado é em: Agronomia ?"
## [1] "O seu doutorado é em: Engenharia Florestal ?"
## [1] "O seu doutorado é em: Bacharel em Agronomia ?"
## [1] "Esta pessoa não explicou o que quis dizer com 'outro'"
## [1] "O seu doutorado é em: Engenharia Agrícola ?"
## [1] "O seu doutorado é em: Agronomia ?"
## [1] "Você ainda trabalha com: Engenharia Agronômica ?"
## [1] "Você ainda trabalha com: Ciências Biológicas ?"
## [1] "O seu doutorado é em: Agronomia ?"
## [1] "Você ainda trabalha com: Engenheiro Florestal ?"
## [1] "Você ainda trabalha com: Genética e Melhoramento de Plantas ?"
## [1] "Esta pessoa não explicou o que quis dizer com 'outro'"
## [1] "Você ainda trabalha com: Agronomia ?"
## [1] "Você ainda trabalha com: Engenharia Agronômica ?"
## [1] "O seu doutorado é em: Agronomia ?"
## [1] "O seu doutorado é em: Agronomia ?"
## [1] "Você ainda trabalha com: Ciências Biológicas ?"
## [1] "Você ainda trabalha com: Agronomia ?"
## [1] "Você ainda trabalha com: Ciências Biológicas ?"
## [1] "O seu doutorado é em: Engenharia Agronômica ?"
## [1] "Você ainda trabalha com: Ciências Biológicas ?"
## [1] "O seu doutorado é em: Agronomia ?"
## [1] "O seu doutorado é em: Biotecnologia ?"
## [1] "O seu doutorado é em: Biologia ?"
## [1] "Esta pessoa não explicou o que quis dizer com 'outro'"
## [1] "Você ainda trabalha com: Biologia ?"
## [1] "O seu doutorado é em: Agronomia ?"
## [1] "O seu doutorado é em: Biologia ?"
## [1] "Você ainda trabalha com: Agronomia ?"
## [1] "Você ainda trabalha com: Melhoramento genético ?"
## [1] "Esta pessoa não explicou o que quis dizer com 'outro'"
## [1] "O seu doutorado é em: Agronomia ?"
## [1] "Você ainda trabalha com: Ciências Biológicas ?"
## [1] "Você ainda trabalha com: Ciências Biológicas ?"
## [1] "Você ainda trabalha com: Agronomia ?"
## [1] "Você ainda trabalha com: Biologia ?"
## [1] "O seu doutorado é em: Agronomia ?"
## [1] "Você ainda trabalha com: Agronomia ?"
## [1] "Esta pessoa não explicou o que quis dizer com 'outro'"
## [1] "O seu doutorado é em: Zootecnia ?"
## [1] "Você ainda trabalha com: Agronomia ?"
## [1] "O seu doutorado é em: Biotecnologia ?"
## [1] "O seu doutorado é em: Agronomia ?"
## [1] "O seu doutorado é em: Agronomia ?"
## [1] "O seu doutorado é em: Agronomia ?"
## [1] "Você ainda trabalha com: Agronomia ?"
## [1] "O seu doutorado é em: Agronomia ?"
## [1] "O seu doutorado é em: Agronomia ?"
## [1] "Você ainda trabalha com: Agronomia ?"
## [1] "O seu doutorado é em: Genética e Melhoramento ?"
## [1] "Você ainda trabalha com: Agronomia ?"
## [1] "O seu doutorado é em: Agronomia ?"
## [1] "O seu doutorado é em: Agronomia ?"
## [1] "Esta pessoa não explicou o que quis dizer com 'outro'"
## [1] "O seu doutorado é em: Agronomia ?"
## [1] "O seu doutorado é em: Biologia ?"
## [1] "O seu doutorado é em: Genética e Melhoramento de Plantas ?"
## [1] "O seu doutorado é em: Agronomia ?"
## [1] "Você ainda trabalha com: Agronomia ?"
## [1] "O seu doutorado é em: Agronomia ?"
## [1] "O seu doutorado é em: Agronomia ?"
## [1] "O seu doutorado é em: Agronomia ?"
## [1] "O seu doutorado é em: Agronomia ?"
## [1] "Esta pessoa não explicou o que quis dizer com 'outro'"
## [1] "O seu doutorado é em: Agronomia ?"
## [1] "O seu doutorado é em: Engeheria em Biotecnologia Vegetal (Chile) ?"
## [1] "Você ainda trabalha com: AGRONOMIA ?"
## [1] "Você ainda trabalha com: Engenharia Agronômica ?"
## [1] "O seu doutorado é em: Agronomia ?"
## [1] "O seu doutorado é em: Agronomia ?"
## [1] "Você ainda trabalha com: Biología ?"
## [1] "O seu doutorado é em: Agronomia ?"
## [1] "O seu doutorado é em: Ciências Biológicas ?"
## [1] "Você ainda trabalha com: Agronomia ?"
## [1] "Você ainda trabalha com: Agronomia ?"
## [1] "O seu doutorado é em: Agronomia ?"
## [1] "O seu doutorado é em: Agronomia ?"
## [1] "O seu doutorado é em: Agronomia ?"
## [1] "O seu doutorado é em: Ciências Biológicas ?"
## [1] "O seu doutorado é em: Agronomia ?"
## [1] "O seu doutorado é em: Agronomia ?"
## [1] "Você ainda trabalha com: Agronomia ?"
## [1] "O seu doutorado é em: Agronomia ?"
## [1] "Você ainda trabalha com: Agronomia ?"
## [1] "O seu doutorado é em: Engenharia Biotecnológica ?"
## [1] "Você ainda trabalha com: Agronomia ?"
## [1] "Você ainda trabalha com: Agronomia ?"
## [1] "O seu doutorado é em: Engenharia Florestal ?"
## [1] "Você ainda trabalha com: Agronomia ?"
## [1] "O seu doutorado é em: Agronomia ?"
## [1] "Você ainda trabalha com: Biologia ?"
## [1] "O seu doutorado é em: Biologia ?"
## [1] "O seu doutorado é em: Ciências Biológicas ?"
## [1] "Você ainda trabalha com: Agronomia ?"
## [1] "Esta pessoa não explicou o que quis dizer com 'outro'"
## [1] "O seu doutorado é em: Agronomia ?"
## [1] "O seu doutorado é em: Engenheiro Agrônomo ?"
## [1] "O seu doutorado é em: Genética e Melhoramento ?"
## [1] "O seu doutorado é em: Agronomia ?"
## [1] "O seu doutorado é em: Agronomia ?"
## [1] "Esta pessoa não explicou o que quis dizer com 'outro'"
## [1] "O seu doutorado é em: Agronomia ?"
## [1] "Você ainda trabalha com: Agronomia ?"
## [1] "Esta pessoa não explicou o que quis dizer com 'outro'"
## [1] "Você ainda trabalha com: Engenharia Agronômica / Licenciatura em Ciências Agrárias ?"
## [1] "Você ainda trabalha com: Ciencias Biologicas ?"
## [1] "Você ainda trabalha com: Agronomia ?"
## [1] "O seu doutorado é em: Eng. Florestal ?"
## [1] "Postdoc"
## [1] "Você ainda trabalha com: Psychology ?"
## [1] "Você ainda trabalha com: Plant Genetics ?"
## [1] "Você ainda trabalha com: Plant Breeding ?"
## [1] "Finished my Masters "
## [1] "Você ainda trabalha com: Soil Sciencies  ?"
## [1] "Masters degree"
## [1] "PhD"

Dica: Identação

Repare a diferença:

# Sem identação
for(i in 1:nrow(dados)){
if(dados$Presente_Ocupação[i] == "Other"){
if(is.na(dados$Explique[i])) {
print("Esta pessoa não explicou o que quis dizer com 'outro'") 
} else {
print(dados$Explique[i])
}
} else if (dados$Presente_Ocupação[i] == "PhD"){
print(paste("O seu doutorado é em:",dados$Background[i], "?"))
} else {
print(paste("Você ainda trabalha com:", dados$Background[i], "?"))
}
}

O editor de código do RStudio tem uma facilitação para identar códigos em R, selecione a área que deseja identar e aperte Ctrl+i.

Agora vamos trabalhar com a coluna 5, que possui a informação o background dos participantes. Repare que a função table retorna diferentes categorias que poderiam ser resumidas em apenas uma, como “Engenharia agronômica” e “Agronomia”. Vamos utilizar um loop para descobrir quais responderam áreas relacionadas à “Agro”. Depois, quais dessas respostas não foram “Agronomia” e pedir para que este participante modifique a resposta digitando apenas “Agronomia”.

Dica: Para identificar o padrão “Agro” podemos utilizar a função grepl.

# Exemplo do uso da função grepl
dados[,5]
##   [1] "Agronomia"                                                
##   [2] "Agronomia"                                                
##   [3] "Biotecnologia"                                            
##   [4] "Licenciatura em Ciências Biológicas"                      
##   [5] "Agronomia"                                                
##   [6] "Agronomia"                                                
##   [7] "Zootecnia"                                                
##   [8] "Agronomia"                                                
##   [9] "Agronomia"                                                
##  [10] "Engenharia Florestal"                                     
##  [11] "Bacharel em Agronomia"                                    
##  [12] "Engenharia Agronômica"                                    
##  [13] "Engenharia Agrícola"                                      
##  [14] "Agronomia"                                                
##  [15] "Engenharia Agronômica"                                    
##  [16] "Ciências Biológicas"                                      
##  [17] "Agronomia"                                                
##  [18] "Engenheiro Florestal"                                     
##  [19] "Genética e Melhoramento de Plantas"                       
##  [20] "Agronomia"                                                
##  [21] "Agronomia"                                                
##  [22] "Engenharia Agronômica"                                    
##  [23] "Agronomia"                                                
##  [24] "Agronomia"                                                
##  [25] "Ciências Biológicas"                                      
##  [26] "Agronomia"                                                
##  [27] "Ciências Biológicas"                                      
##  [28] "Engenharia Agronômica"                                    
##  [29] "Ciências Biológicas"                                      
##  [30] "Agronomia"                                                
##  [31] "Biotecnologia"                                            
##  [32] "Biologia"                                                 
##  [33] "Agronomia"                                                
##  [34] "Biologia"                                                 
##  [35] "Agronomia"                                                
##  [36] "Biologia"                                                 
##  [37] "Agronomia"                                                
##  [38] "Melhoramento genético"                                    
##  [39] "FAEM - UFPEL"                                             
##  [40] "Agronomia"                                                
##  [41] "Ciências Biológicas"                                      
##  [42] "Ciências Biológicas"                                      
##  [43] "Agronomia"                                                
##  [44] "Biologia"                                                 
##  [45] "Agronomia"                                                
##  [46] "Agronomia"                                                
##  [47] "Eng. Agronômica"                                          
##  [48] "Zootecnia"                                                
##  [49] "Agronomia"                                                
##  [50] "Biotecnologia"                                            
##  [51] "Agronomia"                                                
##  [52] "Agronomia"                                                
##  [53] "Agronomia"                                                
##  [54] "Agronomia"                                                
##  [55] "Agronomia"                                                
##  [56] "Agronomia"                                                
##  [57] "Agronomia"                                                
##  [58] "Genética e Melhoramento"                                  
##  [59] "Agronomia"                                                
##  [60] "Agronomia"                                                
##  [61] "Agronomia"                                                
##  [62] "Ciências bilógicas"                                       
##  [63] "Agronomia"                                                
##  [64] "Biologia"                                                 
##  [65] "Genética e Melhoramento de Plantas"                       
##  [66] "Agronomia"                                                
##  [67] "Agronomia"                                                
##  [68] "Agronomia"                                                
##  [69] "Agronomia"                                                
##  [70] "Agronomia"                                                
##  [71] "Agronomia"                                                
##  [72] "Agronomia"                                                
##  [73] "Agronomia"                                                
##  [74] "Engeheria em Biotecnologia Vegetal (Chile)"               
##  [75] "AGRONOMIA"                                                
##  [76] "Engenharia Agronômica"                                    
##  [77] "Agronomia"                                                
##  [78] "Agronomia"                                                
##  [79] "Biología"                                                 
##  [80] "Agronomia"                                                
##  [81] "Ciências Biológicas"                                      
##  [82] "Agronomia"                                                
##  [83] "Agronomia"                                                
##  [84] "Agronomia"                                                
##  [85] "Agronomia"                                                
##  [86] "Agronomia"                                                
##  [87] "Ciências Biológicas"                                      
##  [88] "Agronomia"                                                
##  [89] "Agronomia"                                                
##  [90] "Agronomia"                                                
##  [91] "Agronomia"                                                
##  [92] "Agronomia"                                                
##  [93] "Engenharia Biotecnológica"                                
##  [94] "Agronomia"                                                
##  [95] "Agronomia"                                                
##  [96] "Engenharia Florestal"                                     
##  [97] "Agronomia"                                                
##  [98] "Agronomia"                                                
##  [99] "Biologia"                                                 
## [100] "Biologia"                                                 
## [101] "Ciências Biológicas"                                      
## [102] "Agronomia"                                                
## [103] "Agronomia"                                                
## [104] "Agronomia"                                                
## [105] "Engenheiro Agrônomo"                                      
## [106] "Genética e Melhoramento"                                  
## [107] "Agronomia"                                                
## [108] "Agronomia"                                                
## [109] "Biotecnologia"                                            
## [110] "Agronomia"                                                
## [111] "Agronomia"                                                
## [112] "Biotecnologia"                                            
## [113] "Engenharia Agronômica / Licenciatura em Ciências Agrárias"
## [114] "Ciencias Biologicas"                                      
## [115] "Agronomia"                                                
## [116] "Eng. Florestal"                                           
## [117] "Genetics"                                                 
## [118] "Psychology"                                               
## [119] "Plant Genetics"                                           
## [120] "Plant Breeding"                                           
## [121] "Climate Change"                                           
## [122] "Soil Sciencies "                                          
## [123] "Animal Science"                                           
## [124] "Animal Breeding and Genetics"
grepl("Agro", dados[,5]) # Quais linhas contém os caracteres "Agro"
##   [1]  TRUE  TRUE FALSE FALSE  TRUE  TRUE FALSE  TRUE  TRUE FALSE  TRUE  TRUE
##  [13] FALSE  TRUE  TRUE FALSE  TRUE FALSE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE
##  [25] FALSE  TRUE FALSE  TRUE FALSE  TRUE FALSE FALSE  TRUE FALSE  TRUE FALSE
##  [37]  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE  TRUE  TRUE  TRUE FALSE
##  [49]  TRUE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE FALSE  TRUE  TRUE
##  [61]  TRUE FALSE  TRUE FALSE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
##  [73]  TRUE FALSE FALSE  TRUE  TRUE  TRUE FALSE  TRUE FALSE  TRUE  TRUE  TRUE
##  [85]  TRUE  TRUE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE FALSE  TRUE  TRUE FALSE
##  [97]  TRUE  TRUE FALSE FALSE FALSE  TRUE  TRUE  TRUE FALSE FALSE  TRUE  TRUE
## [109] FALSE  TRUE  TRUE FALSE  TRUE FALSE  TRUE FALSE FALSE FALSE FALSE FALSE
## [121] FALSE FALSE FALSE FALSE
dados[grepl("Agro", dados[,5]),5]
##  [1] "Agronomia"                                                
##  [2] "Agronomia"                                                
##  [3] "Agronomia"                                                
##  [4] "Agronomia"                                                
##  [5] "Agronomia"                                                
##  [6] "Agronomia"                                                
##  [7] "Bacharel em Agronomia"                                    
##  [8] "Engenharia Agronômica"                                    
##  [9] "Agronomia"                                                
## [10] "Engenharia Agronômica"                                    
## [11] "Agronomia"                                                
## [12] "Agronomia"                                                
## [13] "Agronomia"                                                
## [14] "Engenharia Agronômica"                                    
## [15] "Agronomia"                                                
## [16] "Agronomia"                                                
## [17] "Agronomia"                                                
## [18] "Engenharia Agronômica"                                    
## [19] "Agronomia"                                                
## [20] "Agronomia"                                                
## [21] "Agronomia"                                                
## [22] "Agronomia"                                                
## [23] "Agronomia"                                                
## [24] "Agronomia"                                                
## [25] "Agronomia"                                                
## [26] "Agronomia"                                                
## [27] "Eng. Agronômica"                                          
## [28] "Agronomia"                                                
## [29] "Agronomia"                                                
## [30] "Agronomia"                                                
## [31] "Agronomia"                                                
## [32] "Agronomia"                                                
## [33] "Agronomia"                                                
## [34] "Agronomia"                                                
## [35] "Agronomia"                                                
## [36] "Agronomia"                                                
## [37] "Agronomia"                                                
## [38] "Agronomia"                                                
## [39] "Agronomia"                                                
## [40] "Agronomia"                                                
## [41] "Agronomia"                                                
## [42] "Agronomia"                                                
## [43] "Agronomia"                                                
## [44] "Agronomia"                                                
## [45] "Agronomia"                                                
## [46] "Agronomia"                                                
## [47] "Agronomia"                                                
## [48] "Engenharia Agronômica"                                    
## [49] "Agronomia"                                                
## [50] "Agronomia"                                                
## [51] "Agronomia"                                                
## [52] "Agronomia"                                                
## [53] "Agronomia"                                                
## [54] "Agronomia"                                                
## [55] "Agronomia"                                                
## [56] "Agronomia"                                                
## [57] "Agronomia"                                                
## [58] "Agronomia"                                                
## [59] "Agronomia"                                                
## [60] "Agronomia"                                                
## [61] "Agronomia"                                                
## [62] "Agronomia"                                                
## [63] "Agronomia"                                                
## [64] "Agronomia"                                                
## [65] "Agronomia"                                                
## [66] "Agronomia"                                                
## [67] "Agronomia"                                                
## [68] "Agronomia"                                                
## [69] "Agronomia"                                                
## [70] "Agronomia"                                                
## [71] "Agronomia"                                                
## [72] "Agronomia"                                                
## [73] "Engenharia Agronômica / Licenciatura em Ciências Agrárias"
## [74] "Agronomia"
for(i in 1:nrow(dados)){
  if(grepl("Agro", dados[i,5])){
    if(dados[i,5] != "Agronomia"){
     print("Por favor, substitua sua resposta por Agronomia.") 
    }
  } 
}
## [1] "Por favor, substitua sua resposta por Agronomia."
## [1] "Por favor, substitua sua resposta por Agronomia."
## [1] "Por favor, substitua sua resposta por Agronomia."
## [1] "Por favor, substitua sua resposta por Agronomia."
## [1] "Por favor, substitua sua resposta por Agronomia."
## [1] "Por favor, substitua sua resposta por Agronomia."
## [1] "Por favor, substitua sua resposta por Agronomia."
## [1] "Por favor, substitua sua resposta por Agronomia."

Repare que o código acima não retorna as linhas que não estão corretas, apenas imprime a mensagem. Para isso, precisamos armazenar essas linhas em um vetor e depois acessá-las.

homog <- vector()
for(i in 1:nrow(dados)){
  if(grepl("Agro", dados[i,5])){
    if(dados[i,5] != "Agronomia"){
     print("Por favor, substitua sua resposta por Agronomia.") 
     homog <- c(homog, i)
    }
  } 
}
## [1] "Por favor, substitua sua resposta por Agronomia."
## [1] "Por favor, substitua sua resposta por Agronomia."
## [1] "Por favor, substitua sua resposta por Agronomia."
## [1] "Por favor, substitua sua resposta por Agronomia."
## [1] "Por favor, substitua sua resposta por Agronomia."
## [1] "Por favor, substitua sua resposta por Agronomia."
## [1] "Por favor, substitua sua resposta por Agronomia."
## [1] "Por favor, substitua sua resposta por Agronomia."
homog
## [1]  11  12  15  22  28  47  76 113

Como você faria para corrigir esses elementos errados? Tente!

‘dados[homog, 5] <- “Agronomia”’

While

Nesse tipo de estrutura de repetição a tarefa será realizada até que seja atingida determinada condição.

x <- 1

while(x < 5){
  x <- x + 1
  cat(x)
}
## 2345

É muito importante que nessa estrutura a condição seja atingida, caso contrário o loop irá funcionar infinitamente e você terá que interrompê-lo por meios externos. Um exemplo desses “meios externos” no RStudio é clicar no simbolo em vermelho no canto direito superior da janela do console. Você também pode apertar Ctrl+C no console.

Não é muito difícil disso acontecer, basta um pequeno erro como:

x <- 1

while(x < 5){
  x + 1
  cat(x)
}

Aqui podemos utilizar os comandos break e next para atender a outras condições, como:

x <- 1

while(x < 5){
  x <- x + 1
  if(x==4) break
  cat(x)
}
## 23
x <- 1

while(x < 5){
  x <- x + 1
  if(x==4) next
  cat(x)
}
## 235

Repeat

Esta estrutura também exige uma condição de parada, mas esta condição é necessariamente colocada dentro do bloco de código com o uso do break. Ela então repete o bloco de código até a condição o interrompa.

x <- 1
repeat{
  x <- x+1
  cat(x)
  if(x==4) break
}
## 234

Loops dentro de loops

É possível também utilizarmos estruturas de repetição dentro de estruturas de repetição. Por exemplo, se quisermos trabalhar tanto nas colunas como nas linhas de uma matrix.

# Criando uma matrix vazia
ex_mat <- matrix(nrow=10, ncol=10)

# cada número dentro da matrix será o produto no índice da coluna pelo índice da linha
for(i in 1:dim(ex_mat)[1]) {
  for(j in 1:dim(ex_mat)[2]) {
    ex_mat[i,j] = i*j
  }
}

Outro exemplo de uso:

var1 <- c("fertilizante1", "fertilizante2")
var2 <- c("ESS", "URO", "GRA")

w <- 1
for(i in var1){
  for(j in var2){
    nome_arquivo <- paste0(i,"_planta_",j,".txt")
    arquivo <- data.frame("bloco" = "fake_data", "tratamento" ="fake_data")
    write.table(arquivo, file = nome_arquivo)
    w <- w + 1
  }
}

# Verifique seu diretorio de trabalho, arquivos devem ter sido gerados

Se estiver adiantada/o em relação aos colegas, você já pode fazer os exercícios da Sessão 3, se não, faça-os em outro momento e nos envie dúvidas pelo fórum.

Algumas dicas:

  • Cuidado ao rodar o mesmo comando mais de uma vez, algumas variáveis podem não ser mais como eram antes. Para que o comando funcione da mesma forma é necessário que os objetos de entrada estejam da forma como você espera.
  • Lembrem-se que = é para definir objetos e == é o sinal de igualdade.
  • Nas estruturas condicionais e de repetição, lembrem-se que é necessário manter a sintaxe esperada: If(){} e for(i in 1:10){}. No for, podemos trocar a letra que será o índice, mas é sempre necessário fornecer uma sequência de inteiros ou caracteres.
  • Usar identação ajuda a visualizar o começo e fim de cada estrutura de código e facilita o abrir e fechar de chaves. Identação são aqueles espaços que usamos antes da linha, como:
# Criando uma matrix vazia
ex_mat <- matrix(nrow=10, ncol=10)

# cada número dentro da matrix será o produto no índice da coluna pelo índice da linha
for(i in 1:dim(ex_mat)[1]) {   # Primeiro nível, não tem espaço
  for(j in 1:dim(ex_mat)[2]) { # Segundo nível tem um espaço (tab)
    ex_mat[i,j] = i*j          # Terceiro nível tem dois espaços
  }                            # Fechei o segundo nível
}                              # Fechei o primeiro nível

Vetorização

Embora loops sejam intuitivos e mais fáceis de entender, eles são mais lentos e menos eficientes do que a vetorização. A vetorização é uma técnica que permite aplicar operações em todos os elementos de um vetor ou matriz de uma só vez, sem a necessidade de iterar sobre cada elemento individualmente.

Aqui esta um simples exemplo de um codigo não vetorizado (utilizando loop) e sua versão vetorizada:

# Não vetorizado (usando loop)
numeros <- 1:5
resultado_loop <- numeric(length(numeros))
for(i in 1:length(numeros)) {
    resultado_loop[i] <- numeros[i] * 2
}

# Abordagem vetorizada
numeros <- 1:5
resultado_vetorizado <- numeros * 2

resultado_loop == resultado_vetorizado
## [1] TRUE TRUE TRUE TRUE TRUE

Essa transformação de código pode se tornar mais complexa dependendo do cenário. Por exemplo, pense como seria uma versão vetorizada do loop anterior:

# Não vetorizado (usando loop)
ex_mat <- matrix(nrow=10, ncol=10)

for(i in 1:dim(ex_mat)[1]) {   
  for(j in 1:dim(ex_mat)[2]) { 
    ex_mat[i,j] = i*j          
  }                            
}

# Vetorizado?

Aqui é um bom momento para você praticar a utilizar de uma ferramenta AI para te ajudar a transformar o código em uma versão vetorizada. Você pode utilizar o chatgpt ou o copilot, por exemplo. Compare o resultado do código fornecido com o que você gerou com o loop para verificar se a ferramenta está realmente fazendo o que você deseja. Essa transformação vale a pena se o código em loop estiver muito demorado ou se você tiver que rodar o mesmo código muitas vezes.

’ex_mat <- outer(1:10, 1:10, “*“)’

Criando funções

Se você já está se sentindo confortável com o uso de loops, você pode estar se perguntando: “E se eu quiser fazer isso várias vezes?” ou “E se eu quiser aplicar essa lógica a diferentes conjuntos de dados?”. É aqui que as funções entram em cena.

Podemos criar funções personalizadas para realizar tarefas específicas. A sintaxe básica para criar uma função no R é a seguinte:

minha_funcao <- function(arg1, arg2) {
  # Código da função
  resultado <- arg1 + arg2
  return(resultado)
}

A função minha_funcao recebe dois argumentos (arg1 e arg2) e retorna a soma deles. Você pode chamar essa função passando os valores desejados:

resultado <- minha_funcao(3, 5)
resultado  # Saída: 8
## [1] 8

Exemplo de função personalizada com vetorização:

soma_vetorizada <- function(vetor) {
  # Verifica se o vetor é numérico
  if (!is.numeric(vetor)) {
    stop("O vetor deve ser numérico.")
  }
  # Realiza a soma dos elementos do vetor
  # A função sum() já é vetorizada, então não precisamos de um loop
  # para somar os elementos
  soma <- sum(vetor)
  
  # Padronizando z-score
  z_score <- (vetor - mean(vetor)) / sd(vetor)

  resultado <- list(soma = soma, z_score = z_score)
  return(resultado)
}

# Chamando a função
resultado_vetorizado <- soma_vetorizada(c(1, 2, 3, 4, 5))
resultado_vetorizado 
## $soma
## [1] 15
## 
## $z_score
## [1] -1.2649111 -0.6324555  0.0000000  0.6324555  1.2649111

Exemplo de função utilizando a data.frame como entrada. Note o uso repetitivo da função vai exigir que o dado de entrada tenha o mesmo formato ou pelo menos as colunas que serão utilizadas na função. Uma boa prática é verificar se as colunas necessárias estão presentes no data.frame antes de realizar os cálculos.

head(campo1)
##   clone altura diametro idade corte   volume
## 1 GRA02   30.1     0.26     3 FALSE 1.597287
## 2 URO01   30.4     0.30     4 FALSE 2.147760
## 3 URO03   40.0     0.36     5 FALSE 4.069440
## 4 GRA02   30.2     0.24     3 FALSE 1.365523
## 5 GRA01   30.6     0.27     4 FALSE 1.751131
## 6 URO01   40.1     0.35     5  TRUE 3.856116
calc_volume <- function(data_frame) {
  # Verifica se as colunas necessárias estão presentes
  if (!all(c("diametro", "altura") %in% colnames(data_frame))) {
    stop("As colunas 'diametro' e 'altura' devem estar presentes no data frame.")
  }
  
  # Calcula o volume
  volume <- 3.14 * ((data_frame$diametro / 2)^2) * data_frame$altura
  
  return(volume)
}

Família de funções apply

A família de funções apply também podem funcionar como um estrutura de repetição. Sua sintaxe é mais enxuta quando comparada com for ou while e pode facilitar a elaboração do código.

Aqui vamos exemplificar o uso de algumas dessas funções.

apply

A função apply é a base de todas as outras funções da família, portanto a compreensão do funcionamento desta é essencial para entender as demais. Se buscar no help da função, ele indicará que os argumentos da função consistem em: apply(X, MARGIN, FUN, …). Sendo X o conjunto de dados em formato de array (incluindo matrix, que consiste num array de dimensão 2), MARGIN será 1 se a ação deverá ser aplicada à linhas, 2 se for aplicada a colunas e c(1,2) se for aplicada a ambas; FUN é a função que indica ação.

Num simples exemplo temos a matrix:

ex_mat <- matrix(seq(0,21,3), nrow = 2)

Se quisermos somar os elementos das colunas usamos:

apply(ex_mat, 2, sum)
## [1]  3 15 27 39

Se quisermos somar os elementos das linhas:

apply(ex_mat, 1, sum)
## [1] 36 48

Se fossemos utilizar o for para realizar essa tarefa:

# Soma das colunas
for(i in 1:dim(ex_mat)[2]){
  print(sum(ex_mat[,i]))
}
## [1] 3
## [1] 15
## [1] 27
## [1] 39
# Soma das linhas
for(i in 1:dim(ex_mat)[1]){
  print(sum(ex_mat[i,]))
}
## [1] 36
## [1] 48

Agora um exemplo utilizando uma função personalizada. Vamos criar um função para a padronização z-score, que é uma transformação comum em estatística. A função zscore irá calcular o z-score de um vetor de números. O z-score é calculado subtraindo a média do vetor e dividindo pelo desvio padrão.

# Definindo a função
zscore <- function(vetor) {
  # Padronizando z-score
  resultado <- (vetor - mean(vetor)) / sd(vetor)
  return(resultado)
}

# Aplicando a função à matriz
resultados_linhas <- apply(ex_mat, 1, function(x) zscore(x)) # nas linhas
resultados_linhas
##            [,1]       [,2]
## [1,] -1.1618950 -1.1618950
## [2,] -0.3872983 -0.3872983
## [3,]  0.3872983  0.3872983
## [4,]  1.1618950  1.1618950
resultados_colunas <- apply(ex_mat, 2, function(x) zscore(x)) # nas colunas
resultados_colunas
##            [,1]       [,2]       [,3]       [,4]
## [1,] -0.7071068 -0.7071068 -0.7071068 -0.7071068
## [2,]  0.7071068  0.7071068  0.7071068  0.7071068

lapply

Se diferencia do apply por poder receber vetores e listas (mais utilizado com listas) e devolver o resultado em uma lista.

ex_list <- list(A=matrix(seq(0,21,3), nrow = 2), 
                B=matrix(seq(0,14,2), nrow = 2), 
                C= matrix(seq(0,39,5), nrow = 2))
str(ex_list)
## List of 3
##  $ A: num [1:2, 1:4] 0 3 6 9 12 15 18 21
##  $ B: num [1:2, 1:4] 0 2 4 6 8 10 12 14
##  $ C: num [1:2, 1:4] 0 5 10 15 20 25 30 35

Para selecionar a segunda coluna de todas as matrizes

lapply(ex_list, "[", 2)
## $A
## [1] 3
## 
## $B
## [1] 2
## 
## $C
## [1] 5

Usando com uma função personalizada:

# Aplicando a função zscore à lista
resultados <- lapply(ex_list, function(x) apply(x, 1, zscore))
resultados
## $A
##            [,1]       [,2]
## [1,] -1.1618950 -1.1618950
## [2,] -0.3872983 -0.3872983
## [3,]  0.3872983  0.3872983
## [4,]  1.1618950  1.1618950
## 
## $B
##            [,1]       [,2]
## [1,] -1.1618950 -1.1618950
## [2,] -0.3872983 -0.3872983
## [3,]  0.3872983  0.3872983
## [4,]  1.1618950  1.1618950
## 
## $C
##            [,1]       [,2]
## [1,] -1.1618950 -1.1618950
## [2,] -0.3872983 -0.3872983
## [3,]  0.3872983  0.3872983
## [4,]  1.1618950  1.1618950

sapply

sapply é uma variação de lapply que tenta simplificar o resultado. Ele aplica uma função a cada elemento de uma lista ou vetor, assim como lapply, mas tenta retornar um vetor, matriz ou array — em vez de sempre retornar uma lista.

sapply(ex_list, "[",2)
## A B C 
## 3 2 5
# Aplicando a função zscore à lista
resultados <- sapply(ex_list, function(x) apply(x, 1, zscore))
resultados
##               A          B          C
## [1,] -1.1618950 -1.1618950 -1.1618950
## [2,] -0.3872983 -0.3872983 -0.3872983
## [3,]  0.3872983  0.3872983  0.3872983
## [4,]  1.1618950  1.1618950  1.1618950
## [5,] -1.1618950 -1.1618950 -1.1618950
## [6,] -0.3872983 -0.3872983 -0.3872983
## [7,]  0.3872983  0.3872983  0.3872983
## [8,]  1.1618950  1.1618950  1.1618950

tapply

Esta função é um pouco diferente das demais, ela exige que exista alguma variável categórica (fator) para aplicar ação separadamente conforme suas categorias (levels). Por isso, normalmente é aplicada a data.frames.

Vamos utilizar nosso conjunto de dados:

str(dados)
## 'data.frame':    124 obs. of  8 variables:
##  $ Data             : chr  "07/04/2025 14:00:00" "07/04/2025 14:00:00" "07/04/2025 14:00:00" "07/04/2025 14:00:00" ...
##  $ Afiliação        : chr  "Rcourse2021" "Rcourse2021" "Rcourse2021" "Rcourse2021" ...
##  $ Longitude        : chr  "-54.5724" "-47.6476" "-48.0547" "-106.6563" ...
##  $ Latitude         : chr  "-25.5263" "-22.725" "-15.911" "52.1418" ...
##  $ Background       : chr  "Agronomia" "Agronomia" "Biotecnologia" "Licenciatura em Ciências Biológicas" ...
##  $ Presente_Ocupação: chr  "PhD" "PhD" "Masters degree" "Other" ...
##  $ Explique         : chr  NA NA NA NA ...
##  $ ConhecimentoR    : chr  "Intermediate" "Intermediate" "Beginner (some knowledge)" "Intermediate" ...
dados$Afiliação  <- as.factor(dados$`Afiliação`)

dados$ConhecimentoR_num <- NA
dados$ConhecimentoR_num[dados$ConhecimentoR == "Advanced"] <- 3
dados$ConhecimentoR_num[dados$ConhecimentoR == "Intermediate"] <- 2
dados$ConhecimentoR_num[dados$ConhecimentoR == "Beginner (some knowledge)"] <- 1
dados$ConhecimentoR_num[dados$ConhecimentoR == "No R knowledge"] <- 0
dados$ConhecimentoR_num[dados$ConhecimentoR == ""] <- NA


tapply(dados$ConhecimentoR_num, dados$Afiliação, mean)
##                                                       Agronomic Engineer 
##                                                                  1.00000 
##                                                         Breeding Insight 
##                                                                  1.75000 
##                                                     CIA Central Pecuario 
##                                                                  0.00000 
##                                                                     INTA 
##                                                                  1.00000 
## National Institute of Innovation and Transfer in Agricultural Technology 
##                                                                  2.00000 
##                                                              Rcourse2021 
##                                                                  1.87069
tapply(dados$ConhecimentoR_num, dados$Afiliação, function(x) mean(x, na.rm = TRUE))
##                                                       Agronomic Engineer 
##                                                                  1.00000 
##                                                         Breeding Insight 
##                                                                  1.75000 
##                                                     CIA Central Pecuario 
##                                                                  0.00000 
##                                                                     INTA 
##                                                                  1.00000 
## National Institute of Innovation and Transfer in Agricultural Technology 
##                                                                  2.00000 
##                                                              Rcourse2021 
##                                                                  1.87069

mapply

A função mapply é uma versão multivariada da função sapply. Ela aplica uma função a múltiplos vetores ou listas, retornando um vetor ou matriz. A sintaxe é semelhante à de sapply, mas permite passar vários argumentos para a função.

# Exemplo de uso do mapply
# Definindo uma função simples
soma <- function(x, y) {
  return(x + y)
}
# Criando dois vetores
vetor1 <- c(1, 2, 3)
vetor2 <- c(4, 5, 6)
# Aplicando a função soma a cada par de elementos dos vetores
resultado_mapply <- mapply(soma, vetor1, vetor2)
print(resultado_mapply)
## [1] 5 7 9
# Exemplo de uso do mapply com mais de dois vetores
# Definindo uma função simples
multiplicacao <- function(x, y, z) {
  return(x * y * z)
}
# Criando três vetores
vetor1 <- c(1, 2, 3)
vetor2 <- c(4, 5, 6)
vetor3 <- c(7, 8, 9)
# Aplicando a função multiplicacao a cada tripla de elementos dos vetores
resultado_mapply <- mapply(multiplicacao, vetor1, vetor2, vetor3)
print(resultado_mapply)
## [1]  28  80 162
# Exemplo de uso do mapply com uma função anônima
# Criando dois vetores
vetor1 <- c(1, 2, 3)
vetor2 <- c(4, 5, 6)
# Aplicando uma função anônima que calcula a soma e o produto
resultado_mapply <- mapply(function(x, y) {
  return(c(soma = x + y, produto = x * y))
}, vetor1, vetor2)
print(resultado_mapply)
##         [,1] [,2] [,3]
## soma       5    7    9
## produto    4   10   18
# Exemplo de uso do mapply com uma função personalizada
# Definindo uma função personalizada
soma_produto <- function(x, y) {
  return(c(soma = x + y, produto = x * y))
}
# Criando dois vetores
vetor1 <- c(1, 2, 3)
vetor2 <- c(4, 5, 6)
# Aplicando a função soma_produto a cada par de elementos dos vetores
resultado_mapply <- mapply(soma_produto, vetor1, vetor2)
print(resultado_mapply)
##         [,1] [,2] [,3]
## soma       5    7    9
## produto    4   10   18
# Exemplo de uso do mapply com uma função personalizada e mais de dois vetores
# Definindo uma função personalizada
soma_produto <- function(x, y, z) {
  return(c(soma = x + y + z, produto = x * y * z))
}
# Criando três vetores
vetor1 <- c(1, 2, 3)
vetor2 <- c(4, 5, 6)
vetor3 <- c(7, 8, 9)
# Aplicando a função soma_produto a cada tripla de elementos dos vetores
resultado_mapply <- mapply(soma_produto, vetor1, vetor2, vetor3)
print(resultado_mapply)
##         [,1] [,2] [,3]
## soma      12   15   18
## produto   28   80  162

Se estiver adiantada/o em relação aos colegas, você já pode fazer os exercícios da Sessão extra, se não, faça-os no conforto do seu lar e nos envie dúvidas pelo fórum.

Formatos Longo e Largo

Na análise e visualização de dados com R, especialmente usando o tidyverse, a estrutura dos seus dados é muito importante. O tidyverse é uma coleção de pacotes do R voltados para ciência de dados, e enfatiza o uso de princípios de dados organizados (“tidy data”). Dados organizados seguem uma estrutura padronizada que facilita o trabalho com eles. Aqui está uma lista de todos os pacotes incluídos no tidyverse:

library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr     1.1.4     ✔ readr     2.1.5
## ✔ forcats   1.0.0     ✔ stringr   1.5.1
## ✔ ggplot2   3.5.2     ✔ tibble    3.2.1
## ✔ lubridate 1.9.4     ✔ tidyr     1.3.1
## ✔ purrr     1.0.4     
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
tidyverse_packages()
##  [1] "broom"         "conflicted"    "cli"           "dbplyr"       
##  [5] "dplyr"         "dtplyr"        "forcats"       "ggplot2"      
##  [9] "googledrive"   "googlesheets4" "haven"         "hms"          
## [13] "httr"          "jsonlite"      "lubridate"     "magrittr"     
## [17] "modelr"        "pillar"        "purrr"         "ragg"         
## [21] "readr"         "readxl"        "reprex"        "rlang"        
## [25] "rstudioapi"    "rvest"         "stringr"       "tibble"       
## [29] "tidyr"         "xml2"          "tidyverse"

Existem dois principais formatos para organizar os dados:

  • Formato largo (wide): uma linha por sujeito, com múltiplas colunas para medidas repetidas.
  • Formato longo (long): uma linha por observação, tornando os dados organizados e compatíveis com ferramentas como o ggplot2.

Vamos considerar um conjunto de dados mostrando a população (em milhões) de 10 países ao longo de três anos:

# Dados no formato largo (estimativas realistas de população em milhões)
data_wide <- tibble(
  country = c(
    "EUA", "Canadá", "México", "Brasil", "Costa Rica",
    "Uruguai", "China", "Japão", "Índia", "Groenlândia"
  ),
  `2000` = c(282, 31, 98, 174, 4, 3.3, 1267, 127, 1050, 0.056),
  `2010` = c(309, 34, 112, 196, 4.5, 3.4, 1340, 128, 1230, 0.057),
  `2020` = c(331, 38, 126, 213, 5, 3.5, 1402, 126, 1380, 0.056)
)

data_wide
## # A tibble: 10 × 4
##    country       `2000`   `2010`   `2020`
##    <chr>          <dbl>    <dbl>    <dbl>
##  1 EUA          282      309      331    
##  2 Canadá        31       34       38    
##  3 México        98      112      126    
##  4 Brasil       174      196      213    
##  5 Costa Rica     4        4.5      5    
##  6 Uruguai        3.3      3.4      3.5  
##  7 China       1267     1340     1402    
##  8 Japão        127      128      126    
##  9 Índia       1050     1230     1380    
## 10 Groenlândia    0.056    0.057    0.056

Use pivot_longer() para converter de formato largo para longo:

data_long <- pivot_longer(data_wide,
  cols = -country,
  names_to = "year",
  values_to = "population"
)

data_long
## # A tibble: 30 × 3
##    country year  population
##    <chr>   <chr>      <dbl>
##  1 EUA     2000         282
##  2 EUA     2010         309
##  3 EUA     2020         331
##  4 Canadá  2000          31
##  5 Canadá  2010          34
##  6 Canadá  2020          38
##  7 México  2000          98
##  8 México  2010         112
##  9 México  2020         126
## 10 Brasil  2000         174
## # ℹ 20 more rows

Note que nosso data.frame foi convertido para o formato tibble. Tibbles são uma versão moderna dos data.frames, projetadas para serem mais fáceis de usar e mais eficientes. Elas fazem parte do pacote tidyverse e são amplamente utilizadas em análises de dados. Veja a comparação abaixo:

Característica data.frame tibble (do pacote tibble)
Base ou Tidyverse Base R Parte do tidyverse
Impressão Imprime tudo Mostra prévia (10 linhas)
Tipos de colunas Pode converter Sem conversão automática
Indexação df[,1] retorna vetor tibble[,1] retorna tibble
Nomes de linha Sempre possui Não usa nomes de linha

A maioria das funções do tidyverse, especialmente o ggplot2, funcionam melhor com dados no formato longo. Veja um exemplo:

ggplot(data_long, aes(x = year, y = population, color = country, group = country)) +
  geom_line(size = 1.2) +
  geom_point(size = 2) +
  labs(
    title = "População ao Longo do Tempo (em Milhões)",
    x = "Ano",
    y = "População (Milhões)"
  ) +
  theme_minimal()
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.

Tabelas em formato largo geralmente são mais fáceis de exportar para CSV ou Excel. Para voltar ao formato largo, use pivot_wider():

data_wide_back <- pivot_wider(data_long,
  names_from = year,
  values_from = population
)

data_wide_back
## # A tibble: 10 × 4
##    country       `2000`   `2010`   `2020`
##    <chr>          <dbl>    <dbl>    <dbl>
##  1 EUA          282      309      331    
##  2 Canadá        31       34       38    
##  3 México        98      112      126    
##  4 Brasil       174      196      213    
##  5 Costa Rica     4        4.5      5    
##  6 Uruguai        3.3      3.4      3.5  
##  7 China       1267     1340     1402    
##  8 Japão        127      128      126    
##  9 Índia       1050     1230     1380    
## 10 Groenlândia    0.056    0.057    0.056

Introdução ao uso do pipe

O operador pipe (%>%) é uma ferramenta poderosa em R, especialmente com o tidyverse. Ele permite encadear funções de forma clara e legível, evitando a necessidade de aninhar chamadas de funções.

data_wide_back <- data_long %>%
  pivot_wider(
    names_from = year,
    values_from = population
  )

Quando se tem várias operações a serem aplicadas a um conjunto de dados, o uso do pipe é ideal:

data_wide_back <- data_long %>%
  pivot_wider(
    names_from = year,
    values_from = population
  ) %>%
  mutate(total_population = `2000` + `2010` + `2020`) %>%
  arrange(desc(total_population))

Outras funções úteis: filter() para filtrar linhas, select() para selecionar colunas:

data_wide_back <- data_long %>%
  pivot_wider(
    names_from = year,
    values_from = population
  ) %>%
  mutate(total_population = `2000` + `2010` + `2020`) %>%
  arrange(desc(total_population)) %>%
  filter(total_population > 1000) %>%
  select(country, total_population)

Também podemos usar summarise() para calcular estatísticas por grupo:

data_summary <- data_long %>%
  group_by(year) %>%
  summarise(
    total_population = sum(population, na.rm = TRUE),
    avg_population = mean(population, na.rm = TRUE),
    max_population = max(population, na.rm = TRUE)
  )

data_summary
## # A tibble: 3 × 4
##   year  total_population avg_population max_population
##   <chr>            <dbl>          <dbl>          <dbl>
## 1 2000             3036.           304.           1267
## 2 2010             3357.           336.           1340
## 3 2020             3625.           362.           1402

O pipe %>% vem do pacote dplyr, mas também está disponível no R base como |>. A principal diferença é que %>% permite o uso do . como marcador de posição:

data_wide %>%
  lm(`2020` ~ `2000`, data = .) %>%
  summary()
## 
## Call:
## lm(formula = `2020` ~ `2000`, data = .)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -105.426   -4.807   -1.463    3.357  130.481 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)    
## (Intercept)   1.5810    23.1470   0.068    0.947    
## `2000`        1.1885     0.0434  27.384 3.41e-09 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 60.18 on 8 degrees of freedom
## Multiple R-squared:  0.9894, Adjusted R-squared:  0.9881 
## F-statistic: 749.9 on 1 and 8 DF,  p-value: 3.409e-09

Já no pipe do R base (|>), você precisa usar uma função anônima:

data_wide |>
  (\(df) lm(`2020` ~ `2000`, data = df))() |>
  summary()
## 
## Call:
## lm(formula = `2020` ~ `2000`, data = df)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -105.426   -4.807   -1.463    3.357  130.481 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)    
## (Intercept)   1.5810    23.1470   0.068    0.947    
## `2000`        1.1885     0.0434  27.384 3.41e-09 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 60.18 on 8 degrees of freedom
## Multiple R-squared:  0.9894, Adjusted R-squared:  0.9881 
## F-statistic: 749.9 on 1 and 8 DF,  p-value: 3.409e-09

Introdução ao ggplot2

O ggplot2 é um pacote poderoso e flexível para criar visualizações em R. Ele segue os princípios da Gramática dos Gráficos, que define componentes estruturados para construir visualizações.

Principais componentes:

  • Dados: Conjunto de dados utilizado.
  • Estéticas (aes): Propriedades visuais como posição, cor, tamanho.
  • Geometrias (geom): Tipos de gráfico, como pontos, linhas, barras.
  • Estatísticas (stat): Transformações aplicadas aos dados.
  • Escalas (scale): Ajustes das mapeamentos estéticos.
  • Coordenadas (coord): Sistema de coordenadas.
  • Facetamento (facet): Painéis múltiplos com subconjuntos dos dados.

Exemplos:

ggplot(data_long, aes(x = year, y = population)) + geom_point()

ggplot(data_long, aes(x = year, y = population, group = country)) +
  geom_line() + geom_point()

ggplot(data_long, aes(x = year, y = population, color = country, group = country)) +
  geom_line()

Com stat_summary:

ggplot(data_long, aes(x = year, y = population)) +
  stat_summary(fun = mean, geom = "line", group = 1) +
  labs(title = "Tendência Média de População")

Com escalas de cor personalizadas:

ggplot(data_long, aes(x = year, y = population, group = country, color = country)) +
  geom_line(size = 1.2) +
  scale_color_manual(values = c("China" = "red", "India" = "orange", "USA" = "blue")) +
  labs(title = "População por País")

Com a paleta viridis:

library(viridis)
## Loading required package: viridisLite
ggplot(data_long, aes(x = year, y = population, group = country, color = country)) +
  geom_line(size = 1.2) +
  scale_color_viridis_d() +
  labs(title = "População por País (Viridis)")

Coordenadas invertidas:

ggplot(data_long %>% filter(year == "2020"), aes(x = country, y = population)) +
  geom_col() +
  coord_flip() +
  labs(title = "População por País em 2020")

Facetamento:

ggplot(data_long, aes(x = year, y = population)) +
  geom_line(group = 1) +
  facet_wrap(~ country) +
  labs(title = "Tendência Populacional por País")

Personalização de rótulos e temas:

ggplot(data_long, aes(x = year, y = population, color = country, group = country)) +
  geom_line(size = 1.2) +
  labs(
    title = "População ao Longo do Tempo por País",
    subtitle = "Dados simulados (em milhões)",
    x = "Ano",
    y = "População (Milhões)",
    caption = "Fonte: Dados simulados"
  ) +
  theme_minimal() + theme(
    plot.title = element_text(size = 18, face = "bold"),
    axis.title = element_text(size = 14),
    legend.title = element_text(size = 12)
  )


Criando mapas com ggplot2

dados <- read.csv("https://breeding-insight.github.io/learn-hub/r-intro/data/dados_2025.csv")

colnames(dados) <- c("Data", "Afiliação", "Longitude", "Latitude", "Formação", "Ocupação_Atual", "Explica", "ConhecimentoR")

dados$ConhecimentoR_num <- NA
dados$ConhecimentoR_num[dados$ConhecimentoR == "Avançado"] <- 3
dados$ConhecimentoR_num[dados$ConhecimentoR == "Intermediário"] <- 2
dados$ConhecimentoR_num[dados$ConhecimentoR == "Iniciante (algum conhecimento)"] <- 1
dados$ConhecimentoR_num[dados$ConhecimentoR == "Sem conhecimento em R"] <- 0

world_map <- map_data("world")
dados$Latitude <- as.numeric(dados$Latitude)
## Warning: NAs introduced by coercion
dados$Longitude <- as.numeric(dados$Longitude)
## Warning: NAs introduced by coercion
# Mapa simples
ggplot() +
  geom_polygon(data = world_map, aes(x = long, y = lat, group = group), fill = "gray90", color = "white") +
  geom_point(data = dados, aes(x = Longitude, y = Latitude), alpha = 0.7) +
  labs(title = "Alunos do curso de R", x = "Longitude", y = "Latitude") +
  theme_minimal()
## Warning: Removed 4 rows containing missing values or values outside the scale range
## (`geom_point()`).

# Com cor por ocupação atual
ggplot() +
  geom_polygon(data = world_map, aes(x = long, y = lat, group = group), fill = "gray90", color = "white") +
  geom_point(data = dados, aes(x = Longitude, y = Latitude, color = Ocupação_Atual), alpha = 0.7) +
  labs(title = "Alunos do curso de R", x = "Longitude", y = "Latitude") +
  theme_minimal()
## Warning: Removed 4 rows containing missing values or values outside the scale range
## (`geom_point()`).

# Paleta viridis (acessível para daltônicos)
ggplot() +
  geom_polygon(data = world_map, aes(x = long, y = lat, group = group), fill = "gray90", color = "white") +
  geom_point(data = dados, aes(x = Longitude, y = Latitude, color = Ocupação_Atual), alpha = 0.7) +
  scale_colour_viridis_d() +
  labs(title = "Alunos do curso de R", x = "Longitude", y = "Latitude") +
  theme_minimal()
## Warning: Removed 4 rows containing missing values or values outside the scale range
## (`geom_point()`).