- Treinamento em Programação no Ambiente R
- Familiarização com a interface do RStudio
- Operações básicas
- Criando objetos
- Segundo dia - retomando os trabalhos
- Importando e exportando dados
- Paradoxo do aniversário
- Estruturas condicionais
- Estruturas de repetição
- Elaboração de funções
- Diferenças entre
cat
,print
epaste
- Rodando outros scripts .R
- Elaboração de gráficos simples
- Aplicações de pacotes
- Gráficos com ggplot
- Algumas ferramentas básicas de análise de dados
- Extra
- Sugestões, críticas, elogios e convites para almoço
Treinamento em Programação no Ambiente R
Esse material foi elaborado para o Treinamento em Programação no Ambiente R organizado pelo GENt, grupo de Divulgação Científica do Programa de Pós-Graduação em Genética e Melhoramento de Plantas da ESALQ- USP, em parceria com o grupo Gfito-LQ, grupo de estudos do Departamento de Fitopatologia e Nematologia.
Você pode acessar mais informações sobre o grupo GENt neste link. No site, você pode encontrar as atividades que temos desenvolvido.
Sugerimos que, antes de iniciar a prática aqui descrita, siga este tutorial para instalação do R e do RStudio.
Pedimos que, em algum momento deste primeiro dia, preencham este formulário. Utilizaremos essas informações no segundo dia de curso.
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 ao decorrer do curso.
Um primeiro script
A janela de edição de código (provavelmente localizada no canto superior esquerdo) você irá utilizar 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:
## 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. E, novamente, selecione a linha e aperte Run
.
O símbolo #
é muito utilizado para realizar comentários ao decorrer do código. Esta é uma ótima prática para deixar o código organizado e para que você possa lembrar mais tarde o que você estava pensando quando o escreveu ou para que outras pessoas possam entendê-lo. Como no exemplo:
## 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 para 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 porCursoR
.
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 precisa obter os dados 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:
Ou seja, você pode utilizar este mesmo comando para realizar esta ação. Esta então será nossa pasta de trabalho. Quando estiver perdido/a ou para ter certeza que o diretório de trabalho foi alterado utilize:
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ê 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 errarmos no código por erros de digitação. Utilizar o Tab
reduzirá significativamente esses erros.
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) #logarítmo na base 10
log(100) #logarítmo 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 seja, o código roda, mas não faz o que você gostaria que ele fizesse. Esse é o tipo de erro mais difícil de ser consertado. 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:
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 +
:
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:
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:
## [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] 1 2 3 4 5 6 7 8 9 10
Podemos utilizar outras funções para gerar sequências, como:
## [1] 0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80
## [18] 85 90 95 100
## [1] 0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80
## [18] 85 90 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:
## [1] 3 4 5 3 4 5
Podemos realizar operações utilizando esses vetores:
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:
## [1] 30.1 30.4 40.0 30.2 30.6 40.1
A linguagem é sensível à letras maiúsculas e minúsculas, portanto x
é diferente de 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. Alguns nomes não podem ser usados por estabelecerem papéis fixos no R, são eles:
- NA - Not available, simboliza dados faltantes
- NaN - Not a number, simboliza indefinições matemáticas
- Inf - Infinite, conceito matemático
- NULL - Null object, simboliza ausência de informação
Podemos então realizar as operações com o objeto criado:
Para realizar a operação o R alinha os dois vetores e realiza a operação elemento à elemento. Observe:
## [1] 30.36 30.70 40.36 30.44 30.87 40.45
## [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 à elemento com todos do maior.
Se caso o menor vetor não for múltiplo do maior, obteremos um aviso:
## 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:
Podemos também aplicar algumas funções, como exemplo:
## [1] 101.59
## [1] 16.93167
## [1] 6.427507
Indexação
Acessamos somente o 3º valor do vetor criado com []
:
Também podemos acessar o número da posição 2 a 4 com:
## [1] 15.35 20.18 15.22
Para obter informações do vetor criado utilize:
## 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:
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:
## Factor w/ 4 levels "GRA01","GRA02",..: 2 3 4 2 1 3
## [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:
## [1] 6
Também há vetores lógicos, que recebem valores de verdadeiro ou falso:
## [1] FALSE FALSE FALSE FALSE FALSE TRUE
Com ele podemos, por exemplo, identificar quais são as posições dos elementos maiores que 40:
## [1] 6
## [1] 40.1
## [1] 40.1
Também podemos localizar elementos específicos com:
## [1] TRUE FALSE TRUE TRUE FALSE FALSE
Também podem ser úteis as funções any
e all
. Procure 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”.
## [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”.
## [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”.
## [1] TRUE TRUE FALSE TRUE TRUE TRUE FALSE TRUE TRUE TRUE
Alguns valores não são iguais. Como isso é possivel?
## [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:
## [1] "TRUE" "vish" "1"
No caso, todos os elementos foram transformados em caracter.
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 no conforto do seu lar e nos envie dúvidas pelo fórum.
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:
## [,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:
## [,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:
## [,1] [,2]
## [1,] 2 14
## [2,] 4 16
## [3,] 6 18
## [4,] 8 20
## [5,] 10 22
## [6,] 12 24
## [,1] [,2]
## [1,] 1 49
## [2,] 4 64
## [3,] 9 81
## [4,] 16 100
## [5,] 25 121
## [6,] 36 144
## [,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:
## [1] 0.24
As vezes pode ser informativo dar nomes às colunas e às linhas da matriz, fazemos isso com:
## 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:
## [1] 3 4 5 3 4 5
Ou também com:
## [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]:
## [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
.
## 'data.frame': 6 obs. of 6 variables:
## $ clone : Factor w/ 4 levels "GRA01","GRA02",..: 2 3 4 2 1 3
## $ 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, o número de elementos em cada coluna tem que ser iguais.
- Caso não saiba o operador ou a função que deve ser utilizada, como o desvio padrão, busque no google algo como “desvio padrão R”, ou melhor “standard deviation R”. Logo nas primeiras páginas você obterá respostas. 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 : Factor w/ 4 levels "GRA01","GRA02",..: 2 3 4 2 1 3
## ..$ 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
## 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
## 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:
## [1] 0.26 0.30 0.36 0.24 0.27 0.35
## [1] 0.26 0.30 0.36 0.24 0.27 0.35
## [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:
## , , 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 no conforto do seu lar e nos envie dúvidas pelo fórum.
Paramos aqui no primeiro dia.
Segundo dia - retomando os trabalhos
Aqui você pode acessar um exemplo de script
.R
para esse primeiro dia.Obtenha o arquivo RData com todos os objetos criados até então no tutorial aqui.
Coloque ambos no seu Diretório de Trabalho
Importando e exportando dados
Os arquivos RData são exclusivos do R, clicando duas vezes no arquivo ou utilizando:
Você vai recuperar todos os objetos gerados até agora no tutorial. Para gerar esse arquivo RData, eu rodei todos os códigos daqui para cima e usei:
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:
Se removermos ele do nosso Ambiente Global com:
Podemos facilmente obtê-lo novamente com:
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 fomatos, como exemplo o pacote xlsx
exporta e importa dados com formato do excel.
Ao exportar, há diversas opções para a formatação do arquivo, é importante considerá-las se o arquivo for usado em outro sofware posteriormente.
Abra os arquivos gerados para visualizar sua formatação.
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")
head(campo1_txt)
head(campo1_csv)
Agora que aprendemos a importar dados, vamos trabalhar com o conjunto gerado a partir do formulário que vocês preencheram.
A planilha com os dados será disponibilizada, adicione-a ao seu diretório de trabalho ou indique o caminho da pasta ao importá-la para dentro do R, como a seguir. Caso esteja difícil encontrá-la, acesse:
Aqui usaremos o argumento stringAsFactors
que impede que o R transforme os vetores da tabela em fatores, os quais são mais difíceis de trabalhar. O argumento na.strings
irá indicar como foram nomeados os dados perdidos.
dados <- read.csv(file = "dados_alunos2020.csv", stringsAsFactors = FALSE, na.strings="-", header = T)
head(dados)
Vamos explorar a estrutura dos dados coletados:
## 'data.frame': 18 obs. of 16 variables:
## $ Timestamp : chr "3/12/2020 14:21:32" "3/12/2020 14:23:09" "3/16/2020 10:14:13" "3/16/2020 10:15:41" ...
## $ Gênero : chr "Feminino" "Feminino" "Feminino" "Masculino" ...
## $ Como.você.está.participando.do.curso. : chr "Presencial" "Presencial" "Remoto" "Remoto" ...
## $ Cidade.de.origem..Ex..Piracicaba.SP. : chr "Piracicaba-SP" "Cuiabá-MT" "São Pauo-SP" "Guarabira-PB" ...
## $ Instituição.em.que.estuda..Ex..ESALQ. : chr "ESALQ" "ESALQ" "ESALQ" "ESALQ" ...
## $ Qual.o.seu.atual.nível.de.formação. : chr "Mestrado" "Graduação" "Pós-doc" "Mestrado" ...
## $ Qual.sua.formação.na.graduação. : chr "Biotecnologia" "Biotecnologia" "Agronomia" "Ciências Agrárias" ...
## $ Área.com.a.qual.mais.se.identifica : chr "Interdiciplinar" "Interdiciplinar" "Biológicas" "Biológicas" ...
## $ Idade..Ex..26. : int 29 22 33 22 28 24 NA 24 25 NA ...
## $ Altura.em.metros..Ex..1.60. : num 1.58 1.57 1.65 178 1.67 ...
## $ Peso.em.Kg..Ex..56. : int 54 56 56 95 58 67 NA 78 62 NA ...
## $ Dia.e.mês.de.aniversário..Ex..19.07. : chr "05/10" "22/04" "12/10" "31/03" ...
## $ Dê.uma.nota.de.0.a.10.para.seu.nível.de.conhecimento.em.R : int 8 6 0 0 1 2 4 0 6 0 ...
## $ Você.utiliza.alguma.outra.linguagem.de.programação. : chr "Python, Bash / Linux" "Python" "" "" ...
## $ Para.que.você.utiliza.ou.utilizará.o.R. : chr "Teste" "Teste" "Análise estatística " "Para plotar gráficos e realizar análise de dados das pesquisas que eu produzir." ...
## $ Qual.a.sua.motivação.para.fazer.este.curso...texto.de.30.a.100.palavras.: chr "Teste" "Teste" "Aprender a usar um programa para análise estatística que é consolidado no mundo da pesquisa." "Tornar mais fácil minha capacidade de produção científica." ...
## [1] 18 16
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:
## [1] "Timestamp"
## [2] "Gênero"
## [3] "Como.você.está.participando.do.curso."
## [4] "Cidade.de.origem..Ex..Piracicaba.SP."
## [5] "Instituição.em.que.estuda..Ex..ESALQ."
## [6] "Qual.o.seu.atual.nível.de.formação."
## [7] "Qual.sua.formação.na.graduação."
## [8] "Área.com.a.qual.mais.se.identifica"
## [9] "Idade..Ex..26."
## [10] "Altura.em.metros..Ex..1.60."
## [11] "Peso.em.Kg..Ex..56."
## [12] "Dia.e.mês.de.aniversário..Ex..19.07."
## [13] "Dê.uma.nota.de.0.a.10.para.seu.nível.de.conhecimento.em.R"
## [14] "Você.utiliza.alguma.outra.linguagem.de.programação."
## [15] "Para.que.você.utiliza.ou.utilizará.o.R."
## [16] "Qual.a.sua.motivação.para.fazer.este.curso...texto.de.30.a.100.palavras."
colnames(dados) = c("horario", "genero", "participacao", "cidade", "instituicao",
"escolaridade", "graduacao", "area", "idade", "altura", "peso",
"aniversario", "conhecimentoR", "linguagens", "usoR", "motivacaoR")
str(dados)
## 'data.frame': 18 obs. of 16 variables:
## $ horario : chr "3/12/2020 14:21:32" "3/12/2020 14:23:09" "3/16/2020 10:14:13" "3/16/2020 10:15:41" ...
## $ genero : chr "Feminino" "Feminino" "Feminino" "Masculino" ...
## $ participacao : chr "Presencial" "Presencial" "Remoto" "Remoto" ...
## $ cidade : chr "Piracicaba-SP" "Cuiabá-MT" "São Pauo-SP" "Guarabira-PB" ...
## $ instituicao : chr "ESALQ" "ESALQ" "ESALQ" "ESALQ" ...
## $ escolaridade : chr "Mestrado" "Graduação" "Pós-doc" "Mestrado" ...
## $ graduacao : chr "Biotecnologia" "Biotecnologia" "Agronomia" "Ciências Agrárias" ...
## $ area : chr "Interdiciplinar" "Interdiciplinar" "Biológicas" "Biológicas" ...
## $ idade : int 29 22 33 22 28 24 NA 24 25 NA ...
## $ altura : num 1.58 1.57 1.65 178 1.67 ...
## $ peso : int 54 56 56 95 58 67 NA 78 62 NA ...
## $ aniversario : chr "05/10" "22/04" "12/10" "31/03" ...
## $ conhecimentoR: int 8 6 0 0 1 2 4 0 6 0 ...
## $ linguagens : chr "Python, Bash / Linux" "Python" "" "" ...
## $ usoR : chr "Teste" "Teste" "Análise estatística " "Para plotar gráficos e realizar análise de dados das pesquisas que eu produzir." ...
## $ motivacaoR : chr "Teste" "Teste" "Aprender a usar um programa para análise estatística que é consolidado no mundo da pesquisa." "Tornar mais fácil minha capacidade de produção científica." ...
Paradoxo do aniversário
Nossa primeira análise com esses dados envolverá um problema denominado “Paradoxo do aniversário”, que afirma que em um grupo de 23 pessoas (ou mais), escolhidas aleatoriamente, há mais de 50% de chance de duas pessoas terem a mesma data de aniversário.
Primeiro, vamos verificar em quantos somos, contando o número de linhas, para isso use a função nrow
.
## [1] 18
Vamos então verificar se temos no nosso grupo pessoas que compartilham o mesmo dia de aniversário.
Podemos verificar isso facilmente com a função table
, que indica a frequência de cada observaçã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:
## [1] "dois não é maior que três"
- Teste o nível de conhecimento em R obtidos no formulaŕio (13ª coluna) pela segunda pessoa que o respondeu (linha 2). Envie uma mensagem motivacional se ela não possuir qualquer conhecimento (nota 0), outra se possuir algum conhecimento (restante das notas). (dica: o sinal
==
se refere a “exatamente igual a”)
if(dados[2,13] == 0){
print("Nunca é tarde para começar!")
} else {
print("Já pegou o embalo, agora é só continuar!")
}
## [1] "Já pegou o embalo, agora é só continuar!"
Podemos espeficiar mais do que uma condição repetindo a estrutura if
else
:
if(dados[2,13] == 0){
print("Nunca é tarde para começar!")
} else if (dados[2,13] > 0 & dados[2,13] < 5){
print("Já pegou o embalo, agora é só continuar!")
} else {
print("Nos avise se estivermos falando algo errado...hehe")
}
## [1] "Nos avise se estivermos falando algo errado...hehe"
Também podemos fazer uso das funções any
e all
. Será que algum de nós tem mais de 60 anos de idade (idade está na 9ª coluna)? Se sim, diga para essa pessoa tomar cuidado e levar a sério o isolamento.
Lembrando como any
e all
funcionam:
## [1] TRUE
## [1] TRUE
## [1] FALSE
## [1] TRUE
## [1] FALSE
## [1] FALSE
if(any(dados[,9] > 60)){
print("Sabemos que você está entre nós! Para sua segurança, é melhor que fique em casa, esperamos que esteja assistindo remotamente.")
} else{
print("Não há maiores de 60 anos aqui, evitem visitar idosos nesse período, vamos mantê-los seguros.")
}
Ih! Achamos um bug, né? Vamos lidar com ele! O R deu uma dica de onde ele está:
Error in if (any(dados[, 9] > 60)) { :
missing value where TRUE/FALSE needed
dados[,9] # Verificamos que existem dados perdidos
dados[,9] > 60 # Quando comparamos com 60, eles continuam como dados perdidos
any(dados[,9] > 60) # Aqui está o bug! Por padrão o any, quando encontra NA retorna NA
any(dados[,9] > 60, na.rm = TRUE) # Mudamos esse padrão utilizando o argumento para remover os NA
## [1] FALSE FALSE FALSE FALSE FALSE FALSE TRUE FALSE FALSE TRUE TRUE
## [12] FALSE FALSE FALSE FALSE FALSE FALSE FALSE
Pronto! Podemos voltar ao código.
if(any(dados[,9] > 60, na.rm = TRUE)){
print("Sabemos que você está entre nós! Para sua segurança, é melhor que fique em casa, esperamos que esteja assistindo remotamente.")
} else{
print("Não há maiores de 60 anos aqui. Evitem visitar idosos nesse período, vamos mantê-los seguros.")
}
## [1] "Não há maiores de 60 anos aqui. Evitem visitar idosos nesse período, vamos mantê-los seguros."
# ou
if(any(idade_semNA > 60)){
print("Sabemos que você está entre nós! Para sua segurança, é melhor que fique em casa, esperamos que esteja assistindo remotamente.")
} else{
print("Não há maiores de 60 anos aqui. Evitem visitar idosos nesse período, vamos mantê-los seguros.")
}
## [1] "Não há maiores de 60 anos aqui. Evitem visitar idosos nesse período, vamos mantê-los seguros."
- Lembra do paradoxo do aniversário? Verifique se existe uma data repetida no vetor e responda “Existem pessoas aqui que fazem aniversário no mesmo dia” caso exista e “Não temos pessoas com aniversário no mesmo dia aqui” caso contrário.
## Existem pessoas aqui que fazem aniversário no mesmo dia
Switch
Uma outra estrutura que também pode ser usada com o mesmo propósito é o switch
. Esta estrutura é mais utilizada quando trabalhado com caracteres. Por isso vamos aplicá-la para explorar a área (8ª coluna) com que a segunda pessoa se identifica.
switch(dados[2,8],
Exatas = print("Será que aprendeu alguma linhagem de programação na graduação?"),
Interdiciplinar = print("Em que foi a gradução?"),
print("Ta aqui colocando o pezinho na exatas")
)
## [1] "Em que foi a gradução?"
A estrutura switch
costuma ser mais rápida que o if
e else
. Quando lidamos com grande quantidade de dados isso pode ser uma grande vantagem.
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:
## [1] 1
## [1] 2
## [1] 3
## [1] 4
## [1] 5
## [1] 6
## [1] 7
## [1] 8
## [1] 9
## [1] 10
## [1] 5 6 7 8 9 10 11 12 13 14
Nos casos acima, i
funciona como um index 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[i,13] == 0){
print("Nunca é tarde para começar!")
} else if (dados[i,13] > 0 && dados[i,13] < 5){
print("Já pegou o embalo, agora é só continuar!")
} else {
print("Nos avise se estivermos falando algo errado...hehe")
}
}
Dica: Identação
Repare a diferença:
# Sem identação
for(i in 1:nrow(dados)){
if(dados[i,13] == 0){
print("Nunca é tarde para começar!")
} else if (dados[i,13] > 0 && dados[i,13] < 5){
print("Já pegou o embalo, agora é só continuar!")
} else {
print("Nos avise se estivermos falando algo errado...hehe")
}
}
# Com identação correta
for(i in 1:nrow(dados)){
if(dados[i,13] == 0){
print("Nunca é tarde para começar!")
} else if (dados[i,13] > 0 && dados[i,13] < 5){
print("Já pegou o embalo, agora é só continuar!")
} else {
print("Nos avise se estivermos falando algo errado...hehe")
}
}
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 4, que possui a informação da cidade de origem dos participantes. Repare que alguns não colocaram o estado, como o exemplo sugeria. Vamos utilizar um loop para descobrir quais estão faltando. Vamos utilizar a função grepl
para identificar as strings que contém o caracter “-”, aqueles que tiverem consideraremos correto, os que não tiverem, vamos pedir para adicionar mais informações.
## [1] TRUE
for(i in 1:nrow(dados)){
if(grepl("-", dados[i,4])){
cat("Esse/a seguiu o exemplo direitinho. Parabéns!\n")
} else {
cat("Precisamos adicionar mais informações na linha", i, "\n")
}
}
## Esse/a seguiu o exemplo direitinho. Parabéns!
## Esse/a seguiu o exemplo direitinho. Parabéns!
## Esse/a seguiu o exemplo direitinho. Parabéns!
## Esse/a seguiu o exemplo direitinho. Parabéns!
## Esse/a seguiu o exemplo direitinho. Parabéns!
## Esse/a seguiu o exemplo direitinho. Parabéns!
## Esse/a seguiu o exemplo direitinho. Parabéns!
## Esse/a seguiu o exemplo direitinho. Parabéns!
## Precisamos adicionar mais informações na linha 9
## Esse/a seguiu o exemplo direitinho. Parabéns!
## Esse/a seguiu o exemplo direitinho. Parabéns!
## Esse/a seguiu o exemplo direitinho. Parabéns!
## Esse/a seguiu o exemplo direitinho. Parabéns!
## Esse/a seguiu o exemplo direitinho. Parabéns!
## Esse/a seguiu o exemplo direitinho. Parabéns!
## Esse/a seguiu o exemplo direitinho. Parabéns!
## Esse/a seguiu o exemplo direitinho. Parabéns!
## Esse/a seguiu o exemplo direitinho. Parabéns!
Para que seja possível imprimir conteúdo de objetos durante o loop, usamos a função cat
, ela não separa cada resposta em uma linha, precisamos colocar o \n
indicando a quebra de linha.
Agora vamos nos mesmos corrigir essas informações. Podemos armazenar em uma variável a posição das linhas incorretas, então corrigiremos manualmente somente essas:
corrigir <- vector()
for(i in 1:nrow(dados)){
if(grepl("-", dados[i,4])){
cat("Esse/a seguiu o exemplo direitinho. Parabéns!\n")
} else {
cat("Precisamos adicionar mais informações na linha", i, "\n")
corrigir <- c(corrigir, i)
}
}
## Esse/a seguiu o exemplo direitinho. Parabéns!
## Esse/a seguiu o exemplo direitinho. Parabéns!
## Esse/a seguiu o exemplo direitinho. Parabéns!
## Esse/a seguiu o exemplo direitinho. Parabéns!
## Esse/a seguiu o exemplo direitinho. Parabéns!
## Esse/a seguiu o exemplo direitinho. Parabéns!
## Esse/a seguiu o exemplo direitinho. Parabéns!
## Esse/a seguiu o exemplo direitinho. Parabéns!
## Precisamos adicionar mais informações na linha 9
## Esse/a seguiu o exemplo direitinho. Parabéns!
## Esse/a seguiu o exemplo direitinho. Parabéns!
## Esse/a seguiu o exemplo direitinho. Parabéns!
## Esse/a seguiu o exemplo direitinho. Parabéns!
## Esse/a seguiu o exemplo direitinho. Parabéns!
## Esse/a seguiu o exemplo direitinho. Parabéns!
## Esse/a seguiu o exemplo direitinho. Parabéns!
## Esse/a seguiu o exemplo direitinho. Parabéns!
## Esse/a seguiu o exemplo direitinho. Parabéns!
## [1] 9
Como você faria para corrigir esses elementos errados? Tente!
Dica: Primeiro busque quais são as cidades desses elementos (dados[corrigir,4]), depois, faça um novo vetor com os nomes corretos e substitua na tabela
Uma possibilidade de resposta:
dados[corrigir,4]
novo <- c("Piracicaba - SP")
dados[corrigir,4] <- novo
# Verificando se corrigiu
dados[,4]
A coluna 9 da tabela se refere à idade dos participantes, imprima na tela (usando print ou cat) a década em que cada um nasceu, como a seguir: “Nasceu na década de 80”.
Dica: Faça um novo vetor com a subtração das idades pelo ano atual e depois faça um loop com uma condicional para imprimir as mensagens na tela
Uma possibilidade de resposta:
decada <- 2020 - idade_semNA
for(i in 1:length(decada)){
if(decada[i] < 1960){
print("Nasceu antes da década de 60")
} else if(decada[i] > 1960 && decada[i] < 1970){
print("Nasceu na década de 60")
} else if(decada[i] >= 1970 && decada[i] < 1980){
print("Nasceu na década de 70")
} else if(decada[i] >= 1980 && decada[i] < 1990){
print("Nasceu na década de 80")
} else if(decada[i] >= 1990 && decada[i] < 2000){
print("Nasceu na década de 90")
} else {
print("Xóvem")
}
}
## [1] "Nasceu na década de 90"
## [1] "Nasceu na década de 90"
## [1] "Nasceu na década de 80"
## [1] "Nasceu na década de 90"
## [1] "Nasceu na década de 90"
## [1] "Nasceu na década de 90"
## [1] "Nasceu na década de 90"
## [1] "Nasceu na década de 90"
## [1] "Nasceu na década de 90"
## [1] "Nasceu na década de 90"
## [1] "Nasceu na década de 90"
## [1] "Nasceu na década de 90"
## [1] "Nasceu na década de 80"
## [1] "Nasceu na década de 90"
## [1] "Xóvem"
While
Nesse tipo de estrutura de repetição a tarefa será realizada até que seja atingida determinada condição.
## [1] 2
## [1] 3
## [1] 4
## [1] 5
É 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, como, se este utilizando RStudio, clicar no simbolo em vermelho no canto direito superior da janela do console, ou apertar Ctrl+C no console.
Não é muito difícil disso acontecer, basta um pequeno erro como:
Aqui podemos utilizar os comandos break
e next
para atender a outras condições, como:
## [1] 2
## [1] 3
## [1] 2
## [1] 3
## [1] 5
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.
## [1] 2
## [1] 3
## [1] 4
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
}
}
Fizemos um vídeo com mais detalhes sobre loops no R, aumentem nossa quantidade de views e likes por lá.
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 no conforto do seu lar 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
Elaboração de funções
Normalmente é uma boa prática criar um bloco de código se vai realizar aquela ação poucas vezes. Se for realizar várias vezes a ação e de uma vez só, vale a pena fazer um loop. Mas, se for realizar diversas vezes e o objeto de entrada for modificado, vale a pena fazer uma função. E, na hierarquia, quando tiver acumulado muitas funções para realizar uma tarefa mais complexa, vale a pena construir um pacote.
A função também é considerada um objeto no R, portanto você a atribui à uma variável. Procure nomear a função com um nome curto e intuitivo em relação à tarefa que ela executa. Nem sempre é uma tarefa fácil.
Para criar uma função obedeça a seguinte estrutura:
nome_da_funcao <- function(argumento1, argumento2,...){
corpo da função
}
Como exemplo, vamos criar a função quadra
. Estabelecemos os argumentos da função, nesse caso x
. Entre as chaves fica todo o corpo da função. Se você quer que a função retorne algum valor, é necessário utilizar o return
.
## [1] 9
## [1] 16
## [1] 16
O ambiente de variáveis utilizado pela função é diferente do ambiente global em que são armazenadas todos as variáveis já criadas. Variáveis criadas no corpo da função não pertencerão ao ambiente global, mas as contidas no ambiente global podem ser acessadas pela função. Observe:
rm(z) # certificando que não há uma variável/objeto z criada/o
# Na função quadra, criamos uma variável z internamente
quadra(qualquer_nome)
z # mais ele não é criado no ambiente global, só no ambiente interno da função, e z desaparece assim que a função termina sua tarefa
Agora vamos criar uma outra funçao que usa y
, mas não possui y
como argumento. Atenção: não façam isso na rotina de vocês, sempre estabeleçam tudo o que for ser usado no corpo da função nos argumentos dela, estamos fazendo aqui apenas para fins didádicos.
rm(y)
quadra_mais_y <- function(x){
z <- x*x + y
return(z)
}
quadra_mais_y(4) # não temos ainda y
y <- 2
quadra_mais_y(4) # quando temos, a função acessa o y do ambiente global
Agora, vamos criar uma função para calcular o IMC (índice de massa corporal) dos participantes do curso. Lembrando que o IMC é calculado pela divisão do peso pelo quadrado da altura.
## [1] 54 56 56 95 58 67 NA 78 62 NA NA 53 61 67 95 65 89 70
## [1] 1.580 1.570 1.650 178.000 1.670 1.635 NA 1.680
## [9] 1.780 NA NA 1.540 1.580 1.660 1.890 1.590
## [17] 1.760 1.670
calc_IMC <- function(peso, altura){
IMC <- peso/altura^2
return(IMC)
}
calc_IMC(peso=dados$peso, altura=dados$altura)
## [1] 21.631148854 22.718974401 20.569329660 0.002998359 20.796729894
## [6] 25.063359799 NA 27.636054422 19.568236334 NA
## [11] NA 22.347782088 24.435186669 24.314123966 26.595000140
## [16] 25.711008267 28.731921488 25.099501596
Considere a tabela abaixo e faça agora a função dizer para o usuário quantos valores do vetor de IMCs estão em cada uma das categorias, além de retornar o vetor, como já estava fazendo antes.
peso | categoria |
---|---|
Menos do que 18.5 | Abaixo do peso |
Entre 18,5 e 25 | Peso normal |
Entre 25 e 30 | Sobrepeso |
Entre 30 e 35 | Obesidade grau 1 |
Entre 35 e 40 | Obesidade grau 2 |
Mais do que 40 | Obesidade grau 3 |
calc_IMC <- function(peso, altura){
IMC <- peso/altura^2
idx <- sum(IMC < 18.5) # No R FALSE = 0 e TRUE=1, a soma aqui é a mesma coisa que contar o número de TRUEs
cat(idx, "indivíduos estão abaixo do peso")
idx <- sum(IMC >= 18.5 & IMC < 25)
cat(idx, "indivíduos estão com peso normal")
idx <- sum(IMC >= 25 & IMC < 30)
cat(idx, "indivíduos estão com sobrepeso")
idx <- sum(IMC >= 30 & IMC < 35)
cat(idx, "indivíduos estão com obesidade grau 1")
idx <- sum(IMC >= 35 & IMC < 40)
cat(idx, "indivíduos estão com obesidade grau 2")
idx <- sum(IMC >= 40)
cat(idx, "indivíduos estão com obesidade grau 3")
return(IMC)
}
Se é uma função para uso próprio, você saberá como deve ser o objeto de entrada, mas se ela for utilizada por outras pessoas, será necessário, além de uma prévia explicação de suas ações, verificar se o objeto de entrada esta de acordo com o esperado pela função. No nosso exemplo, não faria sentido o usário entrar com números negativos. Faça com que a função retorne um erro caso isso aconteça.
# para testar durante a construção da função
peso <- dados$peso
altura <- dados$altura
calc_IMC <- function(peso, altura){
if(any(peso < 0 | altura < 0)){
stop("Os valores dos argumentos peso e altura não podem ser negativos")
}
IMC <- peso/altura^2
idx <- sum(IMC < 18.5) # No R FALSE = 0 e TRUE=1, a soma aqui é a mesma coisa que contar o número de TRUEs
cat(idx, "indivíduos estão abaixo do peso")
idx <- sum(IMC >= 18.5 & IMC < 25)
cat(idx, "indivíduos estão com peso normal")
idx <- sum(IMC >= 25 & IMC < 30)
cat(idx, "indivíduos estão com sobrepeso")
idx <- sum(IMC >= 30 & IMC < 35)
cat(idx, "indivíduos estão com obesidade grau 1")
idx <- sum(IMC >= 35 & IMC < 40)
cat(idx, "indivíduos estão com obesidade grau 2")
idx <- sum(IMC >= 40)
cat(idx, "indivíduos estão com obesidade grau 3")
return(IMC)
}
Para saber mais sobre desenvolvimento de funções acesse aqui e, um pouco mais avançado, aqui.
Diferenças entre cat
, print
e paste
## Este é um exemplo
## NULL
## [1] "Este é um exemplo"
## [1] "Este é um exemplo"
## [1] "Este é um exemplo"
## Este é um exemplo oi
## [1] "Este é um exemplo oi"
## [1] "Este é um exemplooi"
## Este é um exemploEste é um exemploEste é um exemploEste é um exemploEste é um exemplo
## [1] "Este é um exemplo"
## [1] "Este é um exemplo"
## [1] "Este é um exemplo"
## [1] "Este é um exemplo"
## [1] "Este é um exemplo"
## Este é um exemplo
## [1] "Este é um exemplo"
class(exemplo) <- "inventei_uma_classe" # Aqui estou fazendo um objeto de classe S3
print.inventei_uma_classe <- function(x) print("Agora vai printar isso aqui, pq eu quero")
cat(exemplo)
## Este é um exemplo
## [1] "Agora vai printar isso aqui, pq eu quero"
## [1] "Este é um exemplo"
Rodando outros scripts .R
As vezes, parte do seu código demanda que você chame algo que foi rodado em outro script. Muitas pessoas também tem o costume de salvar as funções próprias em um script separado. Vamos fazer isso?
- Abra um novo script .R, copie suas funções para ele e o salve como
funcoes.R
Agora, você pode acessa-las usando:
Se estiver adiantada/o em relação aos colegas, você já pode fazer os exercícios da Sessão 4, se não, faça-os no conforto do seu lar e nos envie dúvidas pelo fórum.
Elaboração de gráficos simples
Para outros dados coletados, vamos gerar alguns gráficos simples utilizando as funções básicas do R. Existem pacotes como o ggplot2
, plotly
e shiny
que possuem ferramentas muito poderosas para construção de gráficos, mas exigem um pouco mais de tempo para aprendizagem de sua sintaxe.
Os tipos mais comuns já possuem funções próprias, mas outros gráficos podem ser customizados de acordo com a necessidade do usuário. Vamos iniciar com um simples gráfico de frequências (ou histograma) para os dados de altura
.
Vamos adicionar alguns argumentos para dar uma personalizada:
breaks
para definir os intervalos para cada barra;
Agora tente fazer o histograma para o peso, aproveite para tentar alterar alguns parâmetros. Em seguida, serão apresentados outros gráficos que poderão ser utilizados.
Salvar gráficos
Os gráficos podem ser salvos através dos menus disponíveis no RStudio, ou através de funções que permitem salvar em formatos específicos. Algumas delas são: pdf(); png(); jpeg(); bitmap(). De maneira geral, o parâmetro primordial é fornecer o nome do arquivo que será gerado (contendo sua extensão). Após abrir a função gráfica, deve-se gerar o gráfico de interesse. Por fim, utiliza-se o comando dev.off() para que saída gráfica volte para o console.
png(filename = "hist_rbase.png")
hist(dados$altura)
dev.off()
png(filename = "hist_rbase.png", width = 1500, height = 1500, res= 300)
hist(dados$altura)
dev.off()
Agora, gere um gráfico e salve-o no formato de seu interesse. Em seguida, crie diversos gráficos dentro de uma mesma função gráfica e estude a saída.
Aplicações de pacotes
Existem diversos pacotes disponíveis para variadas aplicações. Utilizaremos o ggplot2, que está disponível no repositório oficial do R, o CRAN. Portanto para instalá-lo:
Depois disso é necessário recrutá-lo com:
O ggplot2
é um pacote que permite a construção de gráficos estatísticos, suas funcionalidades vão muito além do que está disponível nos gráficos básicos do R. Vamos tentar fazer um exemplo?
Gráficos com ggplot
Antes de começarmos a fazer gráficos, vamos entender um pouco sobre o a dinâmica de funcionamento do ggplot
.
# Caso não tenha mais conjunto dados disponível no seu ambiente de trabalho
dados = read.csv("dados_alunos2020.csv", stringsAsFactors = FALSE)
colnames(dados) = c("horario", "genero", "participacao", "cidade", "instituicao", "escolaridade", "graduacao",
"area", "idade", "altura", "peso", "aniversario", "conhecimentoR", "linguagens", "usoR", "motivacaoR")
horario | genero | participacao | cidade | instituicao | escolaridade | graduacao | area | idade | altura | peso | aniversario | conhecimentoR | linguagens | usoR | motivacaoR |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
3/12/2020 14:21:32 | Feminino | Presencial | Piracicaba-SP | ESALQ | Mestrado | Biotecnologia | Interdiciplinar | 29 | 1.580 | 54 | 05/10 | 8 | Python, Bash / Linux | Teste | Teste |
3/12/2020 14:23:09 | Feminino | Presencial | Cuiabá-MT | ESALQ | Graduação | Biotecnologia | Interdiciplinar | 22 | 1.570 | 56 | 22/04 | 6 | Python | Teste | Teste |
3/16/2020 10:14:13 | Feminino | Remoto | São Pauo-SP | ESALQ | Pós-doc | Agronomia | Biológicas | 33 | 1.650 | 56 | 12/10 | 0 | Análise estatística | Aprender a usar um programa para análise estatística que é consolidado no mundo da pesquisa. | |
3/16/2020 10:15:41 | Masculino | Remoto | Guarabira-PB | ESALQ | Mestrado | Ciências Agrárias | Biológicas | 22 | 178.000 | 95 | 31/03 | 0 | Para plotar gráficos e realizar análise de dados das pesquisas que eu produzir. | Tornar mais fácil minha capacidade de produção científica. | |
3/16/2020 12:02:31 | Feminino | Remoto | Piracicaba - SP | UNICAMP | Mestrado | Ciências de Alimentos | Interdiciplinar | 28 | 1.670 | 58 | 19/02 | 1 | Não | Análise de dados | Assegurar que meus dados do mestrado serão reprodutíveis. |
3/16/2020 12:03:07 | Masculino | Presencial | Maceió - AL | ESALQ | Mestrado | Biologia | Biológicas | 24 | 1.635 | 67 | 14/08 | 2 | Para análises de dados | Preciso aprender a fazer gráficos. |
Funções ggplot() e aes()
Para criar qualquer gráfico usando ggplot, utilizamos a função ggplot()
tendo como argumento um data.frame contendo todos os dados que iremos utilizar, independente do estilo de gráfico.
Uma função essencial do ggplot é chamada aesthetic, aes()
, que irá passar todas as informações das variáveis a serem plotadas no gráfico. Dependendo do estilo do gráfico, precisaremos de diferentes variáveis para sua estética. Além disso, dependendo do gráfico, algumas podem ser obrigatórias ou não.
Aqui estão alguns exemplos de parâmetros de aes()
:
- x: variável explicativa
- y: variável resposta
- color: cor do contorno dos objetos
- fill: cor do preenchimento dos objetos
- shape: formato do ponto
- size: tamanho
- linetype: tipo da linha (contínua, pontilhada, tracejada)
Gráficos de dispersão ou scatter plot
Após que sabemos que temos que usar um ggplot()
e um aes()
, vamos ver como isto funciona na prática!
Para fazer um gráfico de dispersão, vamos usar o nosso primeiro “geom”, que será o geom_point()
.
library(ggplot2)
# para cada camada de informação, usaremos uma nova função separada por "+"
ggplot(dados) +
geom_point(aes(x = peso, y = altura))
# vamos adicionando novas informações
ggplot(dados) +
geom_point(aes(x = peso, y = altura, color = genero))
# mas tomar cuidado para não ter tanta informação
ggplot(dados) +
geom_point(aes(x = peso, y = altura, color = genero, size = idade, shape = escolaridade))
Note que as variáveis que estamos usando, como peso, altura e gênero, estão todas dentro do data.frame dados.
Vamos ver como deixar o gráfico mais apresentável.
ggplot(dados) +
geom_point(aes(x = peso, y = altura, color = genero)) +
labs(title = "Meu primeiro scatter plot", x = "Peso (kg)", y = "Altura (m)", color = "Gênero")
ggplot(dados) +
geom_point(aes(x = peso, y = altura, color = genero)) +
labs(title = "Meu primeiro scatter plot", x = "Peso (kg)", y = "Altura (m)", color = "Gênero") +
scale_color_manual(values = c("#F1290A", "#55BB29"))
ggplot(dados) +
geom_point(aes(x = peso, y = altura, color = genero)) +
labs(title = "Meu primeiro scatter plot", x = "Peso (kg)", y = "Altura (m)", color = "Gênero") +
scale_color_manual(values = c("#F1290A", "#55BB29")) +
theme_light() +
theme(legend.position = "bottom")
Sugestão de site para escolher uma paleta de cores: Color-Hex
Outra coisa MUITO IMPORTANTE de se ver são as imagens deste link: ggplot Cheat Sheet
E se fôssemos relacionar o IMC das pessoas às informações de altura e peso?
# Alternativa 1: uma escala de IMC
IMC.numerico = function(m, h){
m/h^2
}
ggplot(dados) +
geom_point(aes(x = peso, y = altura, color = IMC.numerico(peso, altura))) +
labs(x = "Peso (kg)", y = "Altura (m)", color = "IMC") +
scale_color_continuous(low = "blue", high = "red")
# Alternativa 2: categorias de IMC
IMC.categorico = function(m, h){
imc = IMC.numerico(m, h)
for (i in 1:length(imc)) {
if(imc[i] < 18.5) {
return("Abaixo do peso")
} else if(imc[i] < 25) {
return("Normal")
} else if(imc[i] < 30) {
return("Sobrepeso")
} else if(imc[i] < 40) {
return("Obesidade")
} else {
return("Obesidade grave")
}
}
}
ggplot(dados) +
geom_point(aes(x = peso, y = altura, color = IMC.categorico(peso, altura))) +
labs(x = "Peso (kg)", y = "Altura (m)", color = "IMC")
Gráficos de barras e histogramas
Vamos pensar em como informar os perfis de alunos por curso de formação por gênero e por área de interesse.
# GENERO
# posição: empilhamento
ggplot(dados) +
geom_bar(aes(x = graduacao, fill = genero)) +
labs(x = element_blank(), y = "Contagem", fill = "Gênero")
# posição: esquivando
ggplot(dados) +
geom_bar(aes(x = graduacao, fill = genero), position = "dodge") +
labs(x = element_blank(), y = "Contagem", fill = "Gênero")
# AREA DE INTERESSE
# posição: empilhamento
ggplot(dados) +
geom_bar(aes(x = graduacao, fill = area)) +
labs(x = element_blank(), y = "Contagem", fill = "Área de interesse") +
coord_flip()
# posição: esquivando
ggplot(dados) +
geom_bar(aes(x = graduacao, fill = area), position = "dodge") +
labs(x = element_blank(), y = "Contagem", fill = "Área de interesse") +
coord_flip()
Por vezes, é mais interessante subdividir a informação em mais de um gráfico.
ggplot(dados) +
geom_bar(aes(x = graduacao, fill = genero)) +
labs(x = element_blank(), y = "Contagem", fill = "Gênero") +
facet_wrap(~ area) + coord_flip()
ggplot(dados) +
geom_bar(aes(x = graduacao, fill = area)) +
labs(x = element_blank(), y = "Contagem", fill = "Área de interesse") +
facet_wrap(~ genero) + coord_flip()
Outra forma de subdividir um gráfico em vários grupos é usando a camada facet_grid()
, que permite organizar os gráficos do mesmo tipo em linhas, colunas ou matrizes de gráficos.
Para fazermos histogramas, é importante ajustar a largura das barras para representar aquilo que esperamos. Não existe uma regra muito clara que expresse bem qual o número de “bins” que devemos usar, então é importante fazer o teste com vários valores.
# alterando o número de bins
ggplot(dados) +
geom_histogram(aes(x = altura), bins = 10) +
labs(x = "Altura", y = "Contagem")
ggplot(dados) +
geom_histogram(aes(x = altura), bins = 20) +
labs(x = "Altura", y = "Contagem")
# alterando a largura das bins
ggplot(dados) +
geom_histogram(aes(x = altura), binwidth = 0.1) +
labs(x = "Altura", y = "Contagem")
ggplot(dados) +
geom_histogram(aes(x = altura), binwidth = 0.3) +
labs(x = "Altura", y = "Contagem")
Os gráficos de densidade são bem bonitos de fazer, mas eles extrapolam informações a partir dos dados.
Boxplots e violin plots
Estes tipos de gráficos são comumente usados para visualizar as tendências gerais dos dados e são muito utilizados pela comunidade científica.
ggplot(dados) +
geom_boxplot(aes(x = escolaridade, y = conhecimentoR)) +
labs(x = element_blank(), y = "Conhecimento prévio em R")
ggplot(dados) +
geom_violin(aes(x = area, y = conhecimentoR)) +
labs(x = element_blank(), y = "Conhecimento prévio em R")
Agora vamos pensar numa pergunta mais interessante. Será que o número de linguagens que a pessoa conhece previamente está relacionada com o conhecimento prévio em R? Para isto, teremos que descobrir a partir de dados$linguagens
qual a quantidade de linguagens de programação cada pessoa conhece.
Vamos fazer este exercício juntos!
Salvar gráficos do ggplot
Os gráficos podem ser salvos de várias formas diferentes, vamos olhar algumas delas. Podemos utilizar a interface gráfica do RStudio assim como já fizemos antes ou por meio de uma função específica do ggplot.
Usando a função ggsave()
, conseguimos salvar imagens em formatos como: “pdf”, “png”, “jpeg”, “tiff”, “bmp”, “eps”, “ps”, “tex”, “svg”.
# Para salvar gráficos usando comandos, usamos a função ggsave()
ggplot(dados) +
geom_boxplot(aes(x = escolaridade, y = conhecimentoR)) +
labs(x = element_blank(), y = "Conhecimento prévio em R")
# Para o ggsave, podemos ainda ajustar alguns parâmetros como largura, comprimento e resolução
ggsave("boxplot_gg.pdf")
# Outra alternativa, é salvar gráficos em objetos para modificá-los e salvá-los no momento que quisermos
peso_altura = ggplot(dados) +
geom_point(aes(x = peso, y = altura, color = genero)) +
labs(title = "Meu primeiro scatter plot", x = "Peso (kg)", y = "Altura (m)", color = "Gênero")
ggsave(peso_altura, filename = "scatterplot1_gg.png", width = 15, height = 12, units = "cm", dpi = 500)
# Assim não precisamos fazer o gráfico novamente para fazer alguma alteração
peso_altura = peso_altura + theme(legend.position = "bottom")
ggsave(peso_altura, filename = "scatterplot2_gg.png", width = 15, height = 12, units = "cm", dpi = 500)
Algumas ferramentas básicas de análise de dados
Claramente a análise de dados é algo muito específico de cada conjunto de dados e interesses. Vamos aqui mostrar alguns recursos básicos como análise de variância, teste de médias e PCA.
Estatísticas descritivas
Algumas avaliações descritivas podem ser feitas pelo uso do tapply
e de gráficos. A função summary
também da informações gerais do conjunto. É possível usá-la em conjunto com o tapply
.
## 'data.frame': 18 obs. of 16 variables:
## $ horario : chr "3/12/2020 14:21:32" "3/12/2020 14:23:09" "3/16/2020 10:14:13" "3/16/2020 10:15:41" ...
## $ genero : chr "Feminino" "Feminino" "Feminino" "Masculino" ...
## $ participacao : chr "Presencial" "Presencial" "Remoto" "Remoto" ...
## $ cidade : chr "Piracicaba-SP" "Cuiabá-MT" "São Pauo-SP" "Guarabira-PB" ...
## $ instituicao : chr "ESALQ" "ESALQ" "ESALQ" "ESALQ" ...
## $ escolaridade : chr "Mestrado" "Graduação" "Pós-doc" "Mestrado" ...
## $ graduacao : chr "Biotecnologia" "Biotecnologia" "Agronomia" "Ciências Agrárias" ...
## $ area : chr "Interdiciplinar" "Interdiciplinar" "Biológicas" "Biológicas" ...
## $ idade : int 29 22 33 22 28 24 NA 24 25 NA ...
## $ altura : num 1.58 1.57 1.65 178 1.67 ...
## $ peso : int 54 56 56 95 58 67 NA 78 62 NA ...
## $ aniversario : chr "05/10" "22/04" "12/10" "31/03" ...
## $ conhecimentoR: int 8 6 0 0 1 2 4 0 6 0 ...
## $ linguagens : chr "Python, Bash / Linux" "Python" "" "" ...
## $ usoR : chr "Teste" "Teste" "Análise estatística " "Para plotar gráficos e realizar análise de dados das pesquisas que eu produzir." ...
## $ motivacaoR : chr "Teste" "Teste" "Aprender a usar um programa para análise estatística que é consolidado no mundo da pesquisa." "Tornar mais fácil minha capacidade de produção científica." ...
# Certifique-se que esta lidando com variável categórica (fator)
dados$genero <- as.factor(dados$genero)
tapply(dados$altura, dados$genero, summary)
## $Feminino
## Min. 1st Qu. Median Mean 3rd Qu. Max. NA's
## 1.540 1.580 1.590 1.614 1.670 1.680 1
##
## $Masculino
## Min. 1st Qu. Median Mean 3rd Qu. Max. NA's
## 1.635 1.685 1.770 31.121 1.863 178.000 2
## $Feminino
## Min. 1st Qu. Median Mean 3rd Qu. Max. NA's
## 53.00 56.00 58.00 61.22 65.00 78.00 1
##
## $Masculino
## Min. 1st Qu. Median Mean 3rd Qu. Max. NA's
## 62.00 67.00 78.00 79.17 93.50 95.00 2
Análise de variância
Podemos falar que há diferenças significativas entre o peso de homens e mulheres?
mod1 <- lm(peso ~ genero, data = dados)
summary(mod1)
# ou o equivalente
mod1 <- aov(peso ~ genero, data = dados)
summary(mod1)
As funções lm
e summary
diferem apenas na forma de apresentar os resultados. O p-valor nos indica se podemos considerar diferenças do peso conforme o gênero.
Podemos verificar se modelo ajustado atende às pressuposições da análise de variância, através da observação de gráficos. Se você teve aulas de estatística experimental, talvez se lembre disso. Caso contrário, não precisa se preocupar, nosso foco é ensinar vocês sobre programar no R e dar independência para que comecem a analisar seus próprios conjuntos.
Avaliando o clima de Londrina
Vamos utilizar outro conjunto de dados para realizarmos mais avaliações utilizando a função lm
. Acesse o conjunto clima_lond:
Para obter os dados de precipitação da cidade de Londrina no primeiro semestre de 2017. Vamos utilizar as funções tapply
e lm
para avaliar os dados.
## 'data.frame': 181 obs. of 4 variables:
## $ dia : Factor w/ 31 levels "1","2","3","4",..: 1 2 3 4 5 6 7 8 9 10 ...
## $ Mes : Factor w/ 6 levels "Abril","Fevereiro",..: 3 3 3 3 3 3 3 3 3 3 ...
## $ prec.mm: Factor w/ 56 levels "0","0.2","0.3",..: 55 52 26 5 21 1 4 1 1 4 ...
## $ Data : Factor w/ 181 levels "2017-01-01","2017-01-02",..: 1 2 3 4 5 6 7 8 9 10 ...
clima_lond$dia <- as.factor(clima_lond$dia)
# A precipitação nesse caso é uma variável contínua, nao categórica, para transformá-la use:
clima_lond$prec.mm <- as.numeric(as.character(clima_lond$prec.mm))
# Já com o tapply podemos ver as diferenças
tapply(clima_lond$prec.mm, clima_lond$Mes, summary)
## $Abril
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.000 0.000 0.000 4.653 0.650 47.400
##
## $Fevereiro
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.00 0.00 0.00 3.65 2.85 34.80
##
## $Janeiro
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.000 0.000 0.600 8.532 6.600 59.600
##
## $Junho
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.000 0.000 0.000 3.573 0.500 30.600
##
## $Maio
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.000 0.000 0.000 7.406 7.000 48.200
##
## $Março
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.000 0.000 0.000 3.223 1.200 26.200
Repare que os níveis aparecem em ordem alfabética e não conforme o tempo, alteramos isso com:
## [1] "Abril" "Fevereiro" "Janeiro" "Junho" "Maio" "Março"
# A função match vai indicar a posição dos elementos do primeiro vetor no segundo vetor
pos <- match(c("Janeiro", "Fevereiro", "Março", "Abril", "Maio", "Junho"), levels(clima_lond$Mes))
pos
## [1] 3 2 6 1 5 4
# Aqui utilizamos as posições obtidas para reordenar os meses nos níveis do fator
clima_lond$Mes = factor(clima_lond$Mes,
levels(clima_lond$Mes)[pos])
# Refazendo
tapply(clima_lond$prec.mm, clima_lond$Mes, summary)
## $Janeiro
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.000 0.000 0.600 8.532 6.600 59.600
##
## $Fevereiro
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.00 0.00 0.00 3.65 2.85 34.80
##
## $Março
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.000 0.000 0.000 3.223 1.200 26.200
##
## $Abril
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.000 0.000 0.000 4.653 0.650 47.400
##
## $Maio
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.000 0.000 0.000 7.406 7.000 48.200
##
## $Junho
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.000 0.000 0.000 3.573 0.500 30.600
Podemos também avaliar fazendo alguns gráficos:
ggplot(clima_lond) +
geom_point(aes(x = Mes, y = prec.mm)) +
labs(title = "Precipitação x Mês", x = "Meses do ano de 2017", y = "Precipitação em mm")
barplot(tapply(clima_lond$prec.mm, clima_lond$Mes, sum),
main="Total Mensal",
xlab = "Meses do ano de 2017",
ylab = "Precipitação em mm")
# Vamos fazer um gráfico de barras que mostre a soma de precipitação em cada mês
stat_lond <- tapply(clima_lond$prec.mm, clima_lond$Mes, sum)
str(stat_lond)
## num [1:6(1d)] 264.5 102.2 99.9 139.6 229.6 ...
## - attr(*, "dimnames")=List of 1
## ..$ : chr [1:6] "Janeiro" "Fevereiro" "Março" "Abril" ...
# Repare que o resultado do tapply é um vetor com seus elementos nomeados com cada mês
# Para usar o ggplot nesse caso, precisamos elaborar um data.frame cujas colunas sejam as variáveis que utilizaremos
stat_lond_edit <- data.frame("mes" = factor(names(stat_lond),
levels = c("Janeiro", "Fevereiro", "Março", "Abril", "Maio", "Junho")), "soma" = stat_lond)
str(stat_lond_edit)
## 'data.frame': 6 obs. of 2 variables:
## $ mes : Factor w/ 6 levels "Janeiro","Fevereiro",..: 1 2 3 4 5 6
## $ soma: num [1:6(1d)] 264.5 102.2 99.9 139.6 229.6 ...
ggplot(stat_lond_edit) +
geom_bar(aes(x = mes, y = soma), stat="identity") +
labs(title= "Soma da precipitação por mês", x = "Meses do ano de 2017", y = "Soma da precipitação")
Vamos então realizar um análise de variância para medir diferenças entre os meses.
##
## Call:
## lm(formula = prec.mm ~ Mes, data = clima_lond)
##
## Residuals:
## Min 1Q Median 3Q Max
## -8.532 -4.653 -3.573 -0.950 51.068
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 8.532 2.054 4.155 5.09e-05 ***
## MesFevereiro -4.882 2.981 -1.638 0.1033
## MesMarço -5.310 2.904 -1.828 0.0692 .
## MesAbril -3.879 2.929 -1.325 0.1871
## MesMaio -1.126 2.904 -0.388 0.6988
## MesJunho -4.959 2.929 -1.693 0.0922 .
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 11.43 on 175 degrees of freedom
## Multiple R-squared: 0.03264, Adjusted R-squared: 0.004997
## F-statistic: 1.181 on 5 and 175 DF, p-value: 0.3205
Podemos também fazer um teste de médias para diferenciar a precipitação ao decorrer dos meses. Aqui utilizaremos o método de Tukey:
modaov <- aov(prec.mm ~ Mes, data = clima_lond)
tukey.test <- TukeyHSD(x=modaov, 'Mes', conf.level=0.95)
tukey.test
## Tukey multiple comparisons of means
## 95% family-wise confidence level
##
## Fit: aov(formula = prec.mm ~ Mes, data = clima_lond)
##
## $Mes
## diff lwr upr p adj
## Fevereiro-Janeiro -4.88225806 -13.472720 3.708204 0.5747965
## Março-Janeiro -5.30967742 -13.678889 3.059534 0.4504534
## Abril-Janeiro -3.87892473 -12.317591 4.559742 0.7710793
## Maio-Janeiro -1.12580645 -9.495018 7.243405 0.9988508
## Junho-Janeiro -4.95892473 -13.397591 3.479742 0.5380417
## Março-Fevereiro -0.42741935 -9.017881 8.163043 0.9999914
## Abril-Fevereiro 1.00333333 -7.654809 9.661476 0.9994427
## Maio-Fevereiro 3.75645161 -4.834010 12.346914 0.8061715
## Junho-Fevereiro -0.07666667 -8.734809 8.581476 1.0000000
## Abril-Março 1.43075269 -7.007914 9.869419 0.9965219
## Maio-Março 4.18387097 -4.185340 12.553082 0.7022258
## Junho-Março 0.35075269 -8.087914 8.789419 0.9999965
## Maio-Abril 2.75311828 -5.685548 11.191785 0.9355052
## Junho-Abril -1.08000000 -9.587555 7.427555 0.9991318
## Junho-Maio -3.83311828 -12.271785 4.605548 0.7798252
Avaliando experimento de café
Agora, trabalharemos com dados de um experimento de café. Acesse aqui:
- Arquivo cafe.txt
O experimento trata-se de dados em blocos completos casualizados de 10 progênies de café. Nele a coluna rep
refere-se à repetição, prog
indica o indivíduo da progênie (prog) e colheita
indica a colheita.
## 'data.frame': 120 obs. of 4 variables:
## $ rep : int 1 1 1 1 1 1 1 1 1 1 ...
## $ prog : int 1 2 3 4 5 6 7 8 9 10 ...
## $ colheita: int 1 1 1 1 1 1 1 1 1 1 ...
## $ prod : num 4.3 13.2 1.59 2.76 11.38 ...
Não esqueça que é necessário que o arquivo esteja no seu ambiente de trabalho ou que você especifique o caminho completo para que o R o encontre!
Para essa análise de dados, nossa variável resposta é a produção (prod
) e a repetição (rep
), a progênie (prog
) e a colheita (colheita
) serão fatores no nosso modelo, identificados por seus níveis.
# Transformar em fator
data$rep <- as.factor(data$rep)
data$prog <- as.factor(data$prog)
data$colheita <- as.factor(data$colheita)
str(data)
## 'data.frame': 120 obs. of 4 variables:
## $ rep : Factor w/ 4 levels "1","2","3","4": 1 1 1 1 1 1 1 1 1 1 ...
## $ prog : Factor w/ 10 levels "1","2","3","4",..: 1 2 3 4 5 6 7 8 9 10 ...
## $ colheita: Factor w/ 3 levels "1","2","3": 1 1 1 1 1 1 1 1 1 1 ...
## $ prod : num 4.3 13.2 1.59 2.76 11.38 ...
# Outra opção
data <- transform(data, rep = factor(rep), prog = factor(prog), colheita = factor(colheita))
str(data)
## 'data.frame': 120 obs. of 4 variables:
## $ rep : Factor w/ 4 levels "1","2","3","4": 1 1 1 1 1 1 1 1 1 1 ...
## $ prog : Factor w/ 10 levels "1","2","3","4",..: 1 2 3 4 5 6 7 8 9 10 ...
## $ colheita: Factor w/ 3 levels "1","2","3": 1 1 1 1 1 1 1 1 1 1 ...
## $ prod : num 4.3 13.2 1.59 2.76 11.38 ...
Vamos primeiro analisar somente os dados referentes à primeira colheita. Podemos fazer um subconjunto:
## 'data.frame': 40 obs. of 4 variables:
## $ rep : Factor w/ 4 levels "1","2","3","4": 1 1 1 1 1 1 1 1 1 1 ...
## $ prog : Factor w/ 10 levels "1","2","3","4",..: 1 2 3 4 5 6 7 8 9 10 ...
## $ colheita: Factor w/ 3 levels "1","2","3": 1 1 1 1 1 1 1 1 1 1 ...
## $ prod : num 4.3 13.2 1.59 2.76 11.38 ...
Repare que, ao fazer o subconjunto, o conjunto de dados ainda mantém os três níveis do fator colheita, embora agora só tenhamos um. Isso pode ser um problema para a nossa análise. Portanto, devemos remover os níveis excedentes:
## 'data.frame': 40 obs. of 4 variables:
## $ rep : Factor w/ 4 levels "1","2","3","4": 1 1 1 1 1 1 1 1 1 1 ...
## $ prog : Factor w/ 10 levels "1","2","3","4",..: 1 2 3 4 5 6 7 8 9 10 ...
## $ colheita: Factor w/ 1 level "1": 1 1 1 1 1 1 1 1 1 1 ...
## $ prod : num 4.3 13.2 1.59 2.76 11.38 ...
Agora podemos rodar nosso modelo de análise de variância.
# Modelo
Modelo1 <- aov(prod ~ rep + prog,
contrasts = list(prog = "contr.sum"),
data = Colheita_1)
anova(Modelo1)
## Analysis of Variance Table
##
## Response: prod
## Df Sum Sq Mean Sq F value Pr(>F)
## rep 3 58.90 19.633 2.1836 0.113071
## prog 9 410.32 45.591 5.0708 0.000475 ***
## Residuals 27 242.75 8.991
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Essa análise variância exige alguns pressupostos, podemos verificar eles nos nossos dados usando:
####################################################
###verificar Pressupostos da análise de variância###
####################################################
names(Modelo1)
## [1] "coefficients" "residuals" "effects" "rank"
## [5] "fitted.values" "assign" "qr" "df.residual"
## [9] "contrasts" "xlevels" "call" "terms"
## [13] "model"
Modelo1_residuals <- Modelo1$residuals #armazenando os erros ou resíduos
# teste de Normalidade DOS ERROS##
#---------------------------------#
shapiro.test (Modelo1_residuals) # Hipótese de Nulidade
##
## Shapiro-Wilk normality test
##
## data: Modelo1_residuals
## W = 0.96494, p-value = 0.2461
# a hipótese de que os erros são normais, nesse caso, como o p-value = 0.24
# ou seja, é maior que >0.05 ou 0.01 (alfa adotado), não se rejeita a hipotese de normalidade
Vamos trabalhar um poquinho com as informações da ANOVA? Primeiro, guardaremos o valor do quadrado médio:
## [1] 8.990907
E a média da primeira colheita da nossa variável resposta (produção):
## [1] 8.54525
Com eles podemos calcular o coeficiente de variação (CV):
## [1] 35.08948
Calcule o CVe e QME para a colheita 2
Crie uma função calcular o CVe
Possibilidade de respostas:
CV_E <- function(anova, med){
QME <- anova(anova)["Residuals", "Mean Sq"]
CVe <- (sqrt(QME)/med)*100
return(CVe)
}
##
CV_E(anova = Modelo1, med = med)
## [1] 35.08948
Podemos também calcular a herdabilidade da característica produção:
n_rep <- nlevels(Colheita_1$rep)
VG <- (anova(Modelo1)["prog", "Mean Sq"]- QME)/n_rep
VE <- QME
H_2 <- VG/ (VG + VE)
H_2
## [1] 0.5043871
Crie uma função para estimar a herdabilidade
Gerando sorteio para delineamento experimental
Que tal pensarmos em um delineamento experimental e sortearmos as unidades experimentais? Com o pacote agricolae
elaboraremos o sorteio de um experimento de blocos completos casualizados.
############################
#SORTEIO DE EXPERIMENTOS####
############################
#install.packages("agricolae")
library(agricolae)
trt <- c("0","1","2","5","10","20","50","100","Dina")
rcbd <- design.rcbd(trt, 6, serie = 1, seed = 1, "default") # seed = 1
rcbd # Planilha de campo
## $parameters
## $parameters$design
## [1] "rcbd"
##
## $parameters$trt
## [1] "0" "1" "2" "5" "10" "20" "50" "100" "Dina"
##
## $parameters$r
## [1] 6
##
## $parameters$serie
## [1] 1
##
## $parameters$seed
## [1] 1
##
## $parameters$kinds
## [1] "default"
##
## $parameters[[7]]
## [1] TRUE
##
##
## $sketch
## [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9]
## [1,] "Dina" "5" "50" "0" "1" "20" "2" "100" "10"
## [2,] "1" "2" "100" "0" "10" "20" "Dina" "50" "5"
## [3,] "50" "0" "Dina" "10" "20" "100" "5" "1" "2"
## [4,] "10" "1" "100" "20" "0" "5" "2" "Dina" "50"
## [5,] "2" "20" "1" "50" "5" "10" "100" "Dina" "0"
## [6,] "50" "20" "0" "5" "Dina" "2" "1" "100" "10"
##
## $book
## plots block trt
## 1 11 1 Dina
## 2 12 1 5
## 3 13 1 50
## 4 14 1 0
## 5 15 1 1
## 6 16 1 20
## 7 17 1 2
## 8 18 1 100
## 9 19 1 10
## 10 21 2 1
## 11 22 2 2
## 12 23 2 100
## 13 24 2 0
## 14 25 2 10
## 15 26 2 20
## 16 27 2 Dina
## 17 28 2 50
## 18 29 2 5
## 19 31 3 50
## 20 32 3 0
## 21 33 3 Dina
## 22 34 3 10
## 23 35 3 20
## 24 36 3 100
## 25 37 3 5
## 26 38 3 1
## 27 39 3 2
## 28 41 4 10
## 29 42 4 1
## 30 43 4 100
## 31 44 4 20
## 32 45 4 0
## 33 46 4 5
## 34 47 4 2
## 35 48 4 Dina
## 36 49 4 50
## 37 51 5 2
## 38 52 5 20
## 39 53 5 1
## 40 54 5 50
## 41 55 5 5
## 42 56 5 10
## 43 57 5 100
## 44 58 5 Dina
## 45 59 5 0
## 46 61 6 50
## 47 62 6 20
## 48 63 6 0
## 49 64 6 5
## 50 65 6 Dina
## 51 66 6 2
## 52 67 6 1
## 53 68 6 100
## 54 69 6 10
Podemos exportar e salvar nosso sorteio com:
PCA - Análise de componentes principais
O PCA é uma análise exploratória muito frequente quando utilizada por usuários que possuem muitos dados. Nela, torna-se possível visualizar dados que deveriam ter diversas dimensões em apenas duas componentes mais informativas. Para isto, usamos a função autoplot()
.
# para instalar, use install.packages("ggfortify")
library(ggfortify)
autoplot(prcomp(~ conhecimentoR + altura + peso + idade, data = dados),
data = dados, shape = 'area', colour = 'graduacao', loadings = TRUE, loadings.colour = 'red',
loadings.label = TRUE, loadings.label.colour = 'black',
loadings.label.size = 4) +
labs(shape = "Área de \ninteresse", color = "Formação", title = "PCA")
# Os parâmetros relacionados com "LOADINGS" são na verdade a direção onde a váriável mais cresce em duas dimensões
# Ela serve apenas como uma aproximação, já que os dados reais precisariam de mais dimensões, que nosso olho não pode ver
Agora que você fez um plot de PCA, você pode perceber que ele é apenas uma variação do geom_point()
, isto permite que você adicione todas as camadas de ggplot que você quiser sobre este gráfico. Já fizemos isto com as legendas!
Extra
Pratique gerando relatórios no RStudio
Utilize o R no seu dia-a-dia para ir praticando a linguagem. Além das recomendações contidas na primeira apresentação, recomendamos também dar uma olhada em como gerar documentos em pdf e html usando a Markdown. Utilizamos essa metodologia para gerar este tutorial e outras apresentações do curso. Pode ser muito prático no dia-a-dia!
Para utilizar, será necessário a instalação de outros pacotes. Um deles é o próprio rmarkdown
:
Agora crie um arquivo .Rmd utilizando as facilidades do RStudio, clique no ícone com símbolo +
no canto superior esquerdo. Escolha o opção R Markdown
. Dê um título ao seu arquivo e escolha a opção html
. Ao fazer isso, o RStudio já coloca um template inicial, ja com um cabeçalho:
---
title: "Teste"
author: "Eu"
date: "June 5, 2018"
output: html_document
---
Este é o mais simples possível, você pode otimizá-lo de diversas maneiras. Saiba mais aqui.
O template inicial também traz alguns exemplos de sintaxe do markdown. Observe que utilizando #
para títulos de sessões, ##
para um nível inferior (subtitulos) e assim por diante. Palavras em negrito são escritas em meia a dois *
e existem diversas outras especificações para essa sintaxe. Veja mais sobre ela aqui.
Para compilar o código, basta clicar em Knit
. Ele irá pedir para que o arquivo .Rmd seja salvo com algum nome em algum lugar.
O markdown também é capaz de entender diretamente a linguagem html, também a css e latex. Para essa última, o latex precisa estar instalado e todas suas dependências.
Existem alguns pacotes que fornecem templates mais robustos para produção de htmls. Para esse tutorial utilizando o pacote rmdformats
e personalizamos suas cores. Experimente:
Agora faça o mesmo procedimento, clique no +
, escolha R Markdown
e, antes de escolher um título, mude para From Template
, escolha o HTML readthedown template
. Copie e cole o seguinte texto e aperte Knit
.
# Teste1
Isso aqui é um teste só para dar uma olhada no template
## Testinho
Subsessão
* Item
**negrito**
*itálico*
fiz um [link](https://GENt-esalq.github.io/)!
Saiba mais no tutorial sobre isso no R-bloggers, que acreditamos ser um bom começo! Acesse aqui.
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:
Se quisermos somar os elementos das colunas usamos:
## [1] 3 15 27 39
Se quisermos somar os elementos das linhas:
## [1] 36 48
Se fossemos utilizar o for
para realizar essa tarefa:
## [1] 3
## [1] 15
## [1] 27
## [1] 39
## [1] 36
## [1] 48
lapply
Se diferencia do apply
por poder receber outros tipos de objetos (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
## $A
## [1] 3
##
## $B
## [1] 2
##
## $C
## [1] 5
sapply
A função sapply
funciona como o lapply
a diferença é que ele retorna apenas um valor por componente da lista e os deposita em um vetor de resposta. Como no exemplo:
## A B C
## 12 8 20
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:
## 'data.frame': 18 obs. of 16 variables:
## $ horario : chr "3/12/2020 14:21:32" "3/12/2020 14:23:09" "3/16/2020 10:14:13" "3/16/2020 10:15:41" ...
## $ genero : Factor w/ 2 levels "Feminino","Masculino": 1 1 1 2 1 2 1 1 2 2 ...
## $ participacao : chr "Presencial" "Presencial" "Remoto" "Remoto" ...
## $ cidade : chr "Piracicaba-SP" "Cuiabá-MT" "São Pauo-SP" "Guarabira-PB" ...
## $ instituicao : chr "ESALQ" "ESALQ" "ESALQ" "ESALQ" ...
## $ escolaridade : chr "Mestrado" "Graduação" "Pós-doc" "Mestrado" ...
## $ graduacao : chr "Biotecnologia" "Biotecnologia" "Agronomia" "Ciências Agrárias" ...
## $ area : chr "Interdiciplinar" "Interdiciplinar" "Biológicas" "Biológicas" ...
## $ idade : int 29 22 33 22 28 24 NA 24 25 NA ...
## $ altura : num 1.58 1.57 1.65 178 1.67 ...
## $ peso : int 54 56 56 95 58 67 NA 78 62 NA ...
## $ aniversario : chr "05/10" "22/04" "12/10" "31/03" ...
## $ conhecimentoR: int 8 6 0 0 1 2 4 0 6 0 ...
## $ linguagens : chr "Python, Bash / Linux" "Python" "" "" ...
## $ usoR : chr "Teste" "Teste" "Análise estatística " "Para plotar gráficos e realizar análise de dados das pesquisas que eu produzir." ...
## $ motivacaoR : chr "Teste" "Teste" "Aprender a usar um programa para análise estatística que é consolidado no mundo da pesquisa." "Tornar mais fácil minha capacidade de produção científica." ...
## Biológicas Exatas Interdiciplinar
## 1.363636 5.000000 2.500000
Saiba mais sobre essa família de funções no link
Observe que nas funções apply
podemos trocar as funções prontas do r base por funções personalizadas.
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.
Criando mapas com ggplot
Não vamos entrar em detalhe sobre os códigos que usamos aqui porque ele faz uso do tidyverse
, um pacote que permite manipular os dados com muita flexibilidade, mas ele iria requerer outro curso focado apenas nele! Esta é uma aplicação para mostrar que conseguimos fazer quase tudo com R e ggplot em mãos. O mais difícil é saber manipular os dados…
## ── Attaching packages ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── tidyverse 1.2.1 ──
## ✔ tibble 2.1.3 ✔ purrr 0.3.2
## ✔ tidyr 0.8.3 ✔ dplyr 0.8.3
## ✔ readr 1.3.1 ✔ stringr 1.4.0
## ✔ tibble 2.1.3 ✔ forcats 0.4.0
## ── Conflicts ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag() masks stats::lag()
# Coletando os dados da base por estado
estados = brazilmaps::get_brmap("State")
# Adicionando uma coluna com as siglas dos estados, será importane para a próxima etapa
estados$sigla = c("RO", "AC", "AM", "RR", "PA", "AP", "TO", "MA", "PI", "CE", "RN", "PB", "PE", "AL", "SE", "BA", "MG", "ES", "RJ", "SP", "PR", "SC", "MS", "MT", "GO", "DF", "RS")
# Aqui, estamos pegando as duas últimas letras da cidade de origem da pessoa,
# se ela tiver preenchido corretamente, estas últimas serão o estado, como em
# "Piracicaba - SP". Após isto, fazemos a contagem de pessoas por estado e
# unimos com os dados do brazilmaps
estados = dados %>%
mutate(sigla = str_sub(cidade, nchar(cidade)-1, nchar(cidade))) %>%
group_by(sigla) %>%
summarise(n = n()) %>%
right_join(estados, by = "sigla")
# Aqui usamos um outro tipo de plot, o geom_sf(), que precisa de dados de
# coordenadas geométricas para construir os mapas. O resto envolve apenas
# funções e argumentos que nós conhecemos!!!
ggplot(estados) +
geom_sf(aes(geometry = geometry, fill = n)) +
theme_minimal() + scale_fill_continuous(low = "gray40", high = "red") +
labs(fill = "Número \nde pessoas")
Sugestões, críticas, elogios e convites para almoço
Caso tenha sugestões para aprimoramento desse material, enviar e-mail para gent.esalq@gmail.com
.
Acesse também outros materiais em português produzidos por Cristiane Taniguti, Fernando Correr e Rodrigo Amadeu aqui.
Este material foi produzido por alunos do programa de pós-graduação em Genética e Melhoramento de Plantas. Cristiane Taniguti, Victor Hugo de Mello Pessoa e Ana Letycia Basso Garcia ministraram o Treinamento. Também contamos com os monitores: Getúlio Caixeta, Rafael Yassue, Wellingson, Vitória, Guilherme Hokasa, Fernando Correr, Humberto, Igor Araújo, Jenifer Camila Godoy.
Também recomendamos materiais em inglês aqui.