<- c(4, 5, 6, 444)
x x
[1] 4 5 6 444
Perceba que estamos construindo uma sequência lógica de aprendizado. No Capítulo 4, nos familiarizamos um pouco melhor com comandos no R e o ambiente do RStudio. Nos Capítulo 5 e Capítulo 6, aprendemos os conceitos de objeto e função, respectivamente, utilizando a experiência adquirida no capítulo anterior para criá-los e armazená-los sem a desconfiança inicial de quem nunca teve contato com a linguagem. Por fim, no Capítulo 7 desenvolvemos a capacidade de importar dados de fontes externas ao R – sejam eles do mundo real ou apenas construídos pelo seu professor. Em resumo, você pode pensar que chegamos neste momento com um certo conhecimento e prática na linguagem, aptos então a aprender como modificar um objeto contendo dados.
“Como assim, modificar um objeto?” Significa adicionar, excluir ou alterar dados. De forma resumida, podemos
substituir ou transformar (somando, multiplicando, etc.) determinado dado específico sem alterar o número de linhas e colunas da estrutura;
adicionar ou remover determinado dado específico, alterando o número de linhas ou colunas da estrutura;
Neste capítulo, daremos ênfase a modificação de vetores e data.frames, abrangendo os pontos mencionados acima1.
Lembre-se que um vetor é uma sequência de valores de mesmo tipo, podendo ser interpretado como uma coluna (vetor-coluna) ou como uma linha (vetor-linha). Portanto, se o combinarmos com mais uma coluna/linha, deixará de ser um vetor. Logo, nos concentraremos na substituição, transformação, adição e remoção de um dado específico. Vamos começar com um simples vetor c(4, 5, 6, 444)
, atirbuindo-o ao objeto de nome x
.
<- c(4, 5, 6, 444)
x x
[1] 4 5 6 444
Se quisessemos apenas substituir o seu segundo elemento, como faríamos? Basta atribuir o novo valor que desejamos, através do operador <-
, à segunda posição do vetor x
! Lembre-se, do Capítulo 5, que para nos referimos ao enésimo elemento de um vetor, devemos escrever seu nome, seguido de colchetes, com a posição \(n\) desejada na parte interior.
2] <- 444
x[ x
[1] 4 444 6 444
Podemos também substituir os valores de múltiplas posições, atribuindo um único valor. No exemplo abaixo, o valor 8 será atribuído às posições 1 e 32.
c(1, 3)] <- 8
x[ x
[1] 8 444 8 444
Ou então substituir os valores de múltiplas posições, atribuindo múltiplos valores, de forma paralela. No exemplo abaixo, os valores ‘6’ e ‘12’ serão atribuídos às posições 1 e 3, respectivamente.
c(1, 3)] <- c(6, 12)
x[ x
[1] 6 444 12 444
Ao invés de nos referirmos à posição do dado que queremos alterar, talvez seja mais útil utilizar seu valor propriamente dito, não é? Por exemplo, substituir todos os ‘444’ presentes por ‘9’. Esse procedimento pode ser feito indicando, dentro dos colchetes após o nome do vetor, que queremos nos relacionar com todos os seus elementos de valor igual a ‘444’.
== 444] <- 9
x[x x
[1] 6 9 12 9
E se quiséssemos substituir valores específicos que são diferentes? Aqui, teremos que nos valer do uso do operador %in%
. No exemplo abaixo, iremos substituir todos os ‘4’ e ‘9’ por ‘0’.
%in% c(4, 9)] <- 0
x[x x
[1] 6 0 12 0
Além disso, podemos, por exemplo, ter o desejo de alterar o quarto elemento do vetor x
através da soma, subtração, multiplicação ou divisão. Nesse caso, devemos realizar a operação sobre o valor atual da quarta posição do vetor e atribuir o resultado, através do operador <-
, à essa mesma posição! Vamos multiplicá-lo por 2.
4] <- x[4] * 2
x[ x
[1] 6 0 12 0
A lógica de atribuição é idêntica ao do primeiro exemplo, quando substituímos o elemento da segunda posição! Por fim, note que você pode combinar todos esses comandos. No exemplo abaixo, substiutímos os valores ‘6’ e 24’ pelo valor da terceira posição, dividido por 2, somado mais 9 e 32, respectivamente.
%in% c(6, 12)] <- c((x[3] / 2) + 9, 32)
x[x x
[1] 15 0 32 0
E se quiséssemos adicionar um quinto elemento a esse vetor? Basta atribuir o valor desejado à esta posição, como se estivesse substituindo ou alterando um elemento existente! O R irá automaticamente criar esse espaço.
5] <- 7
x[ x
[1] 15 0 32 0 7
Por outro lado, para remover determinado valor via sua posição, escreva-a dentro dos colchetes precedida pelo sinal de -
e atribua o resultado a objeto de mesmo nome.
<- x[-5]
x x
[1] 15 0 32 0
Você também pode remover elementos de um vetor que correspondam a determinados valores. Novamente, faremos uso do operador %in%
. Dessa vez, também usaremos o operador de negação !
.
<- x[!(x %in% c(15, 32))]
x x
[1] 0 0
Vamos utilizar como base a matriz contendo os números de 1 a 9, disposta em 3 linhas e 3 colunas.
<- matrix(c(1:9), ncol = 3)
matrix matrix
[,1] [,2] [,3]
[1,] 1 4 7
[2,] 2 5 8
[3,] 3 6 9
Observe que agora temos uma estrutura de dados bidimensional. Isso significa que você acessar determinando valor através de sua posição, indicando a linha e a coluna em que está. Para substituir tal valor, podemos aplicar a mesma lógica que utilizamos com vetores. No exemplo abaixo, substituímos o número da posição {linha 2, coluna 2} por 1000.
2, 2] <- 1000
matrix[ matrix
[,1] [,2] [,3]
[1,] 1 4 7
[2,] 2 1000 8
[3,] 3 6 9
Você também pode indicar múltiplas posições para fixar o novo valor. Nesse caso, é necessário inserir dois vetores dentro dos colchetes, represetando as linhas e colunas, respectivamente. O novo valor será atribuído a todas as combinações possíveis de posições geradas pelos vetores. Observe o exemplo abaixo. Nele, estamos substituindo os valores das posições {linha 1, coluna 2}, {linha 1, coluna 3}, {linha 2, coluna 2} e {linha 2, coluna 3} pelo número 500.
c(1,2), c(2,3)] <- 500
matrix[ matrix
[,1] [,2] [,3]
[1,] 1 500 500
[2,] 2 500 500
[3,] 3 6 9
No entanto, esse não é o único jeito de se referir a posição de um elemento de uma matriz. Você pode acessá-lo pensando na matriz como um vetor coluna! Em outras palavras, contabilize cada valor em sequência, partindo da esquerda, de cima para baixo. Nessa indexação imaginária, podemos novamente acessar as posições {linha 1, coluna 3} e {linha 2, coluna 3} através dos índices 7 e 8, respectivamente.
c(7, 8)] <- c(70, 80)
matrix[ matrix
[,1] [,2] [,3]
[1,] 1 500 70
[2,] 2 500 80
[3,] 3 6 9
Para nos referirmos à valores propriamente ditos, o procedimento é o mesmo de um vetor.
== 3] <- 90
matrix[matrix matrix
[,1] [,2] [,3]
[1,] 1 500 70
[2,] 2 500 80
[3,] 90 6 9
%in% c(1, 80)] <- 0
matrix[matrix matrix
[,1] [,2] [,3]
[1,] 0 500 70
[2,] 2 500 0
[3,] 90 6 9
Assim como o procedimento de alterar algum elemento específico.
2, 2] <- matrix[2, 2] * 2
matrix[ matrix
[,1] [,2] [,3]
[1,] 0 500 70
[2,] 2 1000 0
[3,] 90 6 9
E se quiséssemos adicionar um décimo elemento a essa matriz, na posição {linha 1, coluna 4}, seria possível? A resposta é não.
1, 4] <- 50 matrix[
Error in `[<-`(`*tmp*`, 1, 4, value = 50): índice fora de limites
E se tratassemos a matriz como um vetor, como fizemos no início da subseção anterior, funcionaria? Nesse caso, até conseguiriamos atribuir o novo valor, porém a matriz seria realmente convertida em vetor!
10] <- 50
matrix[ matrix
[1] 0 2 90 500 1000 6 70 0 9 50
Na prática, para adicionar valores à uma matriz, devemos adicionar uma nova linha ou coluna, utilizando as funções rbind
e cbind
, respectivamente! É necessário respeitar sua forma retangular. “Mas e se não tivermos valores suficientes para preencher um linha ou coluna nova?” Você pode utilizar NA
! No exemplo abaixo, adicionamos uma nova coluna a nossa matriz base.
<- cbind(matrix, c(10, NA, NA))
matrix matrix
[,1] [,2] [,3] [,4]
[1,] 1 4 7 10
[2,] 2 5 8 NA
[3,] 3 6 9 NA
Por outro lado, para remover determinada linha ou coluna, escreva seu índice dentro dos colchetes precedido pelo sinal de -
, separado por vírgula – lembrando que linhas são escritas antes e colunas depois da vírgula. No final, atribua o resultado a objeto de mesmo nome. Abaixo, removendo a coluna 1 da matriz.
<- matrix[,-1]
matrix matrix
[,1] [,2] [,3]
[1,] 4 7 10
[2,] 5 8 NA
[3,] 6 9 NA
Agora, removendo a linha 2.
<- matrix[-2,]
matrix matrix
[,1] [,2] [,3]
[1,] 4 7 10
[2,] 6 9 NA
Nessa seção, iremos manipular data.frames. Vamos recapitular a Tabela 7.1, que importamos no Capítulo 7.
<- read_csv("dados/estudantes.csv") estudantes
Rows: 5 Columns: 6
── Column specification ────────────────────────────────────────────────────────
Delimiter: ","
chr (3): Nome, comida.favorita, PlanoDeRefeição
dbl (3): matrícula, IDADE, peso
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
estudantes
# A tibble: 5 × 6
matrícula Nome comida.favorita PlanoDeRefeição IDADE peso
<dbl> <chr> <chr> <chr> <dbl> <dbl>
1 1 Jorge Acarajé Regime 18 76
2 2 Laís Macarrão Livre 23 65
3 3 Matheus Carne Regime 22 70
4 4 Laura Frango Livre 21 68
5 5 Nathália Peixe Regime 21 66
Muito do que vimos com relação à matrizes se aplica aos dataframes. Com exceção do exercício imaginário do dataframe como um vetor-coluna, as tarefas de substituição e alteração podem ser realizadas da mesma forma.
2, 2] <- "Maurício"
estudantes[ estudantes
# A tibble: 5 × 6
matrícula Nome comida.favorita PlanoDeRefeição IDADE peso
<dbl> <chr> <chr> <chr> <dbl> <dbl>
1 1 Jorge Acarajé Regime 18 76
2 2 Maurício Macarrão Livre 23 65
3 3 Matheus Carne Regime 22 70
4 4 Laura Frango Livre 21 68
5 5 Nathália Peixe Regime 21 66
c(5,2), c(5,6)] <- list(c(25, 23), c(70,68))
estudantes[ estudantes
# A tibble: 5 × 6
matrícula Nome comida.favorita PlanoDeRefeição IDADE peso
<dbl> <chr> <chr> <chr> <dbl> <dbl>
1 1 Jorge Acarajé Regime 18 76
2 2 Maurício Macarrão Livre 23 68
3 3 Matheus Carne Regime 22 70
4 4 Laura Frango Livre 21 68
5 5 Nathália Peixe Regime 25 70
== "Carne"] <- "Carne Vermelha"
estudantes[estudantes estudantes
# A tibble: 5 × 6
matrícula Nome comida.favorita PlanoDeRefeição IDADE peso
<dbl> <chr> <chr> <chr> <dbl> <dbl>
1 1 Jorge Acarajé Regime 18 76
2 2 Maurício Macarrão Livre 23 68
3 3 Matheus Carne Vermelha Regime 22 70
4 4 Laura Frango Livre 21 68
5 5 Nathália Peixe Regime 25 70
$PlanoDeRefeição[estudantes$Nome %in% c("Jorge", "Maurício")] <- "Regime Forte"
estudantes estudantes
# A tibble: 5 × 6
matrícula Nome comida.favorita PlanoDeRefeição IDADE peso
<dbl> <chr> <chr> <chr> <dbl> <dbl>
1 1 Jorge Acarajé Regime Forte 18 76
2 2 Maurício Macarrão Regime Forte 23 68
3 3 Matheus Carne Vermelha Regime 22 70
4 4 Laura Frango Livre 21 68
5 5 Nathália Peixe Regime 25 70
1, 5] <- estudantes[1, 5] * 2
estudantes[ estudantes
# A tibble: 5 × 6
matrícula Nome comida.favorita PlanoDeRefeição IDADE peso
<dbl> <chr> <chr> <chr> <dbl> <dbl>
1 1 Jorge Acarajé Regime Forte 36 76
2 2 Maurício Macarrão Regime Forte 23 68
3 3 Matheus Carne Vermelha Regime 22 70
4 4 Laura Frango Livre 21 68
5 5 Nathália Peixe Regime 25 70
Para adicionar um novo valor, basta refenciar sua posição. Perceba que, caso não haja observações suficientes, o R automaticamente completará o restante com ´NA`.
1, 7] <- 50
estudantes[ estudantes
# A tibble: 5 × 7
matrícula Nome comida.favorita PlanoDeRefeição IDADE peso ...7
<dbl> <chr> <chr> <chr> <dbl> <dbl> <dbl>
1 1 Jorge Acarajé Regime Forte 36 76 50
2 2 Maurício Macarrão Regime Forte 23 68 NA
3 3 Matheus Carne Vermelha Regime 22 70 NA
4 4 Laura Frango Livre 21 68 NA
5 5 Nathália Peixe Regime 25 70 NA
Para remover uma coluna, escreva seu índice entre os colchetes precedido do sinal de -
. Para remover uma linha, realize o mesmo procedimento, apenas adicionando uma vírgula ao final.
<- estudantes[-7]
estudantes <- estudantes[-2,]
estudantes
estudantes
# A tibble: 4 × 6
matrícula Nome comida.favorita PlanoDeRefeição IDADE peso
<dbl> <chr> <chr> <chr> <dbl> <dbl>
1 1 Jorge Acarajé Regime Forte 36 76
2 3 Matheus Carne Vermelha Regime 22 70
3 4 Laura Frango Livre 21 68
4 5 Nathália Peixe Regime 25 70
A depender do nível de complexidade da tarefa que desejamos executar, as funções básicas não serão adequadas (seja por não existir uma função que faça aquele procedimento ou pela dificuldade de implementação/legibilidade do código). Nessa subseção, aprenderemos três funções do pacote dplyr
que serão tornarão o processo de mainupalação mais rápido, fácil e legível.
Na maioria dos casos, iremos utilizar funções do pacote dplyr
em sequência, isto é, utilizando as transformações anteriores como input para funções seguintes. Por esse motivo, se torna comum o uso do operador Pipe %>%
. Não se assuste.
Vamos retornar com o dataframe estudantes
inicial. Não iremos salvar os resultados para facilitar a demonstração – mas lembre-se, caso você queira que seu dataframe permenaça com as modificações, é necessário atribuí-lo à novo objeto (ou a um objeto com mesmo nome do antigo, substiutindo-o na memória).
Rows: 5 Columns: 6
── Column specification ────────────────────────────────────────────────────────
Delimiter: ","
chr (3): Nome, comida.favorita, PlanoDeRefeição
dbl (3): matrícula, IDADE, peso
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
Imagine que você queira selecionar apenas as colunas “Nome”, “IDADE” e “Peso”. Para executar essa tarefa, podemos utilizar a função select
.
%>%
estudantes select(Nome, IDADE, peso)
# A tibble: 5 × 3
Nome IDADE peso
<chr> <dbl> <dbl>
1 Jorge 18 76
2 Laís 23 65
3 Matheus 22 70
4 Laura 21 68
5 Nathália 21 66
Agora, imagine que você deseja alterar a coluna ‘peso’, somando mais 2 para cada observação. Você pode utilizar a função mutate
.
%>%
estudantes mutate(peso = peso + 2)
# A tibble: 5 × 6
matrícula Nome comida.favorita PlanoDeRefeição IDADE peso
<dbl> <chr> <chr> <chr> <dbl> <dbl>
1 1 Jorge Acarajé Regime 18 78
2 2 Laís Macarrão Livre 23 67
3 3 Matheus Carne Regime 22 72
4 4 Laura Frango Livre 21 70
5 5 Nathália Peixe Regime 21 68
Por fim, vamos supor que você queira filtrar somente as pessoas maiores de 20 anos. Para essa tarefa, podemos utilizar a função filter
.
%>%
estudantes filter(IDADE > 20)
# A tibble: 4 × 6
matrícula Nome comida.favorita PlanoDeRefeição IDADE peso
<dbl> <chr> <chr> <chr> <dbl> <dbl>
1 2 Laís Macarrão Livre 23 65
2 3 Matheus Carne Regime 22 70
3 4 Laura Frango Livre 21 68
4 5 Nathália Peixe Regime 21 66
Se resolvermos utilizar todas essas funções ao mesmo tempo, teremos:
%>%
estudantes select(Nome, IDADE, peso) %>%
mutate(peso = peso + 2) %>%
filter(IDADE > 20)
# A tibble: 4 × 3
Nome IDADE peso
<chr> <dbl> <dbl>
1 Laís 23 67
2 Matheus 22 72
3 Laura 21 70
4 Nathália 21 68
Não iremos, no entanto, abordar a geração de diferentes representações de uma mesma tabela de dados. Todas as tabelas que você receber estarão organizadas de forma apropriada para a execução da tarefa. De qualquer modo, caso tenha interesse em entender melhor este processo e como fazê-lo, veja o Capítulo 5 do livro R for Data Science.↩︎
Note que c(1, 3)
, no interior dos colchetes, também é um vetor. Esse vetor não é armazenado na memória e, nesse contexto, serve para indicar as posições que desejamos substituir.↩︎