Semana 2 - Manipulação de Dados

Aula Prática

Author

Marina Scalon

Published

October 7, 2024

Script utilizado na aula 2 para demostrar as funções do pacote dpyr e tidyr do tidyverse

Instalando os pacotes

Nessa aula vamos utilizar o mesmo conjunto de dados da aula 1 para demostrar as funções dos pacotes tidyr e dplyr do tidyverse. O primeiro passo então é carregar o pacote. Confiram a versão e atualizem para versão 2.0.0 usando a função tidyverse_update()!

── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ dplyr     1.1.4     ✔ readr     2.1.5
✔ forcats   1.0.0     ✔ stringr   1.5.1
✔ ggplot2   3.5.1     ✔ tibble    3.2.1
✔ lubridate 1.9.3     ✔ tidyr     1.3.1
✔ purrr     1.0.2     
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
# tidyverse_update()

Carregando o conjunto de dados

Agora vamos determinar o diretório de trabalho e carregar os dados, conforme aprendemos na aula anterior.

Você deve colocar o diretório de acordo com o seu caminho no computador, e de acordo com a localização dos seus dados.

# setwd("C:/Marina/Pos-doutorado/PNPD_UFPR/Vis Man Dados/Aula 2")
# dados <- read.csv("Dados.csv")
dados <- readr::read_csv('https://raw.githubusercontent.com/scalonmc/VisMan/master/VisManDados/Aula1/dados.csv')
Rows: 129 Columns: 13
── Column specification ────────────────────────────────────────────────────────
Delimiter: ","
chr  (3): Tratamento, especie, Grupo
dbl (10): Amostra, individuo, N, P, Mg, K, Ca, Al_ppm, area, 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.
str(dados)
spc_tbl_ [129 × 13] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
 $ Amostra   : num [1:129] 1 2 3 4 5 6 7 8 9 10 ...
 $ Tratamento: chr [1:129] "Floresta" "Floresta" "Floresta" "Floresta" ...
 $ especie   : chr [1:129] "AT" "AT" "AT" "BC" ...
 $ Grupo     : chr [1:129] "D" "D" "D" "B" ...
 $ individuo : num [1:129] 1 2 3 1 2 3 1 2 3 1 ...
 $ N         : num [1:129] 2.36 2.07 2.03 1.32 1.23 ...
 $ P         : num [1:129] 0.1143 0.1143 0.1214 0.0643 0.0714 ...
 $ Mg        : num [1:129] 0.15 0.18 0.133 0.159 0.113 ...
 $ K         : num [1:129] 1.197 1.444 0.366 0.679 0.957 ...
 $ Ca        : num [1:129] 0.319 0.413 0.371 0.576 0.458 ...
 $ Al_ppm    : num [1:129] 122.8 251.8 206.5 96.8 103.3 ...
 $ area      : num [1:129] 288 262 184 149 263 ...
 $ peso      : num [1:129] 3.63 2.49 2.16 1.86 4.39 ...
 - attr(*, "spec")=
  .. cols(
  ..   Amostra = col_double(),
  ..   Tratamento = col_character(),
  ..   especie = col_character(),
  ..   Grupo = col_character(),
  ..   individuo = col_double(),
  ..   N = col_double(),
  ..   P = col_double(),
  ..   Mg = col_double(),
  ..   K = col_double(),
  ..   Ca = col_double(),
  ..   Al_ppm = col_double(),
  ..   area = col_double(),
  ..   peso = col_double()
  .. )
 - attr(*, "problems")=<externalptr> 

Utilizando as funções do dplyr

Select

A função select() é importante para selecionar ou excluir variáveis (colunas do dataset)

Abaixo, vamos fazer passo a passo:

  1. Selecionar apenas as variáveis categóricas
  2. Excluir variávies não úteis
  3. Condicional, no caso se a variável for numérica usando is.numeric
  4. Selecionar variávels com alguma característica comum utilizando starts_with() ou ends_with()
  5. Alterar ordem para visualização dos dados
categoricas <- select(dados, Tratamento, especie, Grupo) #1
str(categoricas)
tibble [129 × 3] (S3: tbl_df/tbl/data.frame)
 $ Tratamento: chr [1:129] "Floresta" "Floresta" "Floresta" "Floresta" ...
 $ especie   : chr [1:129] "AT" "AT" "AT" "BC" ...
 $ Grupo     : chr [1:129] "D" "D" "D" "B" ...
clean <- select(dados, -Amostra, -individuo) #2
str(clean)
tibble [129 × 11] (S3: tbl_df/tbl/data.frame)
 $ Tratamento: chr [1:129] "Floresta" "Floresta" "Floresta" "Floresta" ...
 $ especie   : chr [1:129] "AT" "AT" "AT" "BC" ...
 $ Grupo     : chr [1:129] "D" "D" "D" "B" ...
 $ N         : num [1:129] 2.36 2.07 2.03 1.32 1.23 ...
 $ P         : num [1:129] 0.1143 0.1143 0.1214 0.0643 0.0714 ...
 $ Mg        : num [1:129] 0.15 0.18 0.133 0.159 0.113 ...
 $ K         : num [1:129] 1.197 1.444 0.366 0.679 0.957 ...
 $ Ca        : num [1:129] 0.319 0.413 0.371 0.576 0.458 ...
 $ Al_ppm    : num [1:129] 122.8 251.8 206.5 96.8 103.3 ...
 $ area      : num [1:129] 288 262 184 149 263 ...
 $ peso      : num [1:129] 3.63 2.49 2.16 1.86 4.39 ...
numericas <- select_if(dados, is.numeric) #3

ppm <- select(clean, ends_with("ppm")) #4
str(ppm)
tibble [129 × 1] (S3: tbl_df/tbl/data.frame)
 $ Al_ppm: num [1:129] 122.8 251.8 206.5 96.8 103.3 ...
ordered <- select(dados, N, P, everything())
head(ordered)
# A tibble: 6 × 13
      N      P Amostra Tratamento especie Grupo individuo    Mg     K    Ca
  <dbl>  <dbl>   <dbl> <chr>      <chr>   <chr>     <dbl> <dbl> <dbl> <dbl>
1  2.36 0.114        1 Floresta   AT      D             1 0.150 1.20  0.319
2  2.07 0.114        2 Floresta   AT      D             2 0.180 1.44  0.413
3  2.03 0.121        3 Floresta   AT      D             3 0.133 0.366 0.371
4  1.32 0.0643       4 Floresta   BC      B             1 0.159 0.679 0.576
5  1.23 0.0714       5 Floresta   BC      B             2 0.113 0.957 0.458
6  1.37 0.0786       6 Floresta   BC      B             3 0.116 0.75  0.347
# ℹ 3 more variables: Al_ppm <dbl>, area <dbl>, peso <dbl>

Rbase

Para fazer a mesma coisa no Rbase
São comandos bem simples que eu acho importante demostrar
O diferencial é precisar verificar o número correspondente da coluna do dataframe
categoricas2 <- dados[2:4] #1
str(categoricas2)
tibble [129 × 3] (S3: tbl_df/tbl/data.frame)
 $ Tratamento: chr [1:129] "Floresta" "Floresta" "Floresta" "Floresta" ...
 $ especie   : chr [1:129] "AT" "AT" "AT" "BC" ...
 $ Grupo     : chr [1:129] "D" "D" "D" "B" ...
clean2 <- dados[-c(1,5)] #2
str(clean)
tibble [129 × 11] (S3: tbl_df/tbl/data.frame)
 $ Tratamento: chr [1:129] "Floresta" "Floresta" "Floresta" "Floresta" ...
 $ especie   : chr [1:129] "AT" "AT" "AT" "BC" ...
 $ Grupo     : chr [1:129] "D" "D" "D" "B" ...
 $ N         : num [1:129] 2.36 2.07 2.03 1.32 1.23 ...
 $ P         : num [1:129] 0.1143 0.1143 0.1214 0.0643 0.0714 ...
 $ Mg        : num [1:129] 0.15 0.18 0.133 0.159 0.113 ...
 $ K         : num [1:129] 1.197 1.444 0.366 0.679 0.957 ...
 $ Ca        : num [1:129] 0.319 0.413 0.371 0.576 0.458 ...
 $ Al_ppm    : num [1:129] 122.8 251.8 206.5 96.8 103.3 ...
 $ area      : num [1:129] 288 262 184 149 263 ...
 $ peso      : num [1:129] 3.63 2.49 2.16 1.86 4.39 ...
nutri <- dados[6:13] #3
str(nutri)
tibble [129 × 8] (S3: tbl_df/tbl/data.frame)
 $ N     : num [1:129] 2.36 2.07 2.03 1.32 1.23 ...
 $ P     : num [1:129] 0.1143 0.1143 0.1214 0.0643 0.0714 ...
 $ Mg    : num [1:129] 0.15 0.18 0.133 0.159 0.113 ...
 $ K     : num [1:129] 1.197 1.444 0.366 0.679 0.957 ...
 $ Ca    : num [1:129] 0.319 0.413 0.371 0.576 0.458 ...
 $ Al_ppm: num [1:129] 122.8 251.8 206.5 96.8 103.3 ...
 $ area  : num [1:129] 288 262 184 149 263 ...
 $ peso  : num [1:129] 3.63 2.49 2.16 1.86 4.39 ...

Slice

A função slice() é importante para selecionar ou excluir observações (linhas do dataset)

Abaixo, vamos fazer passo a passo:

  1. Retirar linhas correspondentes a vegetação “Savana”
  2. Selecionar apenas as linhas correspondentes a vegetação “Savana”
  3. Selecionar n linhas em que a váriavel tem valor mínimo
  4. Selecionar n linhas em que uma variável tem um valor máximo
sem.savana <- slice(clean, -46:-90)
str(sem.savana)
tibble [84 × 11] (S3: tbl_df/tbl/data.frame)
 $ Tratamento: chr [1:84] "Floresta" "Floresta" "Floresta" "Floresta" ...
 $ especie   : chr [1:84] "AT" "AT" "AT" "BC" ...
 $ Grupo     : chr [1:84] "D" "D" "D" "B" ...
 $ N         : num [1:84] 2.36 2.07 2.03 1.32 1.23 ...
 $ P         : num [1:84] 0.1143 0.1143 0.1214 0.0643 0.0714 ...
 $ Mg        : num [1:84] 0.15 0.18 0.133 0.159 0.113 ...
 $ K         : num [1:84] 1.197 1.444 0.366 0.679 0.957 ...
 $ Ca        : num [1:84] 0.319 0.413 0.371 0.576 0.458 ...
 $ Al_ppm    : num [1:84] 122.8 251.8 206.5 96.8 103.3 ...
 $ area      : num [1:84] 288 262 184 149 263 ...
 $ peso      : num [1:84] 3.63 2.49 2.16 1.86 4.39 ...
so.savana <- slice(clean, 46:90)
str(so.savana)
tibble [45 × 11] (S3: tbl_df/tbl/data.frame)
 $ Tratamento: chr [1:45] "Savana" "Savana" "Savana" "Savana" ...
 $ especie   : chr [1:45] "AT" "AT" "AT" "BC" ...
 $ Grupo     : chr [1:45] "D" "D" "D" "B" ...
 $ N         : num [1:45] 2.07 2.36 2.4 1.41 1.55 ...
 $ P         : num [1:45] 0.1071 0.1714 0.1071 0.0786 0.0714 ...
 $ Mg        : num [1:45] 0.22 0.205 0.214 0.171 0.222 ...
 $ K         : num [1:45] 1.303 1.28 1.126 0.814 0.879 ...
 $ Ca        : num [1:45] 0.813 0.825 0.57 0.603 0.968 ...
 $ Al_ppm    : num [1:45] 155 213 155 239 258 ...
 $ area      : num [1:45] 352 378 375 208 574 ...
 $ peso      : num [1:45] 3.4 3.87 5.07 2.68 6.17 ...
menosN <- slice_min(dados, N, n = 5)
head(menosN)
# A tibble: 6 × 13
  Amostra Tratamento especie Grupo individuo     N      P     Mg     K     Ca
    <dbl> <chr>      <chr>   <chr>     <dbl> <dbl>  <dbl>  <dbl> <dbl>  <dbl>
1     112 Savana     SP      S             1 0.612 0.0571 0.0471 0.236 0.0756
2     113 Savana     SP      S             2 0.612 0.0571 0.0537 0.36  0.081 
3     116 Savana     VE      S             2 0.754 0.0571 0.0347 0.326 0.196 
4      44 Floresta   VE      S             2 0.848 0.05   0.0455 0.378 0.188 
5     115 Savana     VE      S             1 0.848 0.05   0.0277 0.254 0.181 
6      82 Campo      SM      S             1 0.848 0.0643 0.0722 0.385 0.172 
# ℹ 3 more variables: Al_ppm <dbl>, area <dbl>, peso <dbl>
maisAl <- slice_max(dados, Al_ppm, n = 5)
head(maisAl)
# A tibble: 5 × 13
  Amostra Tratamento especie Grupo individuo     N      P     Mg     K    Ca
    <dbl> <chr>      <chr>   <chr>     <dbl> <dbl>  <dbl>  <dbl> <dbl> <dbl>
1     247 Savana     QP      D             2  1.40 0.0786 0.0736 0.728 0.398
2     246 Savana     QP      D             1  1.48 0.0857 0.0812 0.632 0.236
3     248 Savana     QP      D             3  1.06 0.0714 0.0728 0.893 0.210
4      31 Floresta   QP      D             1  1.84 0.0714 0.0776 0.376 0.412
5      33 Floresta   QP      D             3  1.32 0.0786 0.0844 0.405 0.515
# ℹ 3 more variables: Al_ppm <dbl>, area <dbl>, peso <dbl>

Rbase

Para fazer a mesma coisa no Rbase
Sem usar a função **subset()** e usando a função **subset()**
so.savana2 <- clean[46:90,]
so.savana3 <- subset(clean, Tratamento == "Savana")

sem.savana2 <- clean[-(46:90),]
sem.savana3 <- subset(clean, Tratamento != "Savana")

Filter

A função filter() funciona para seleção condicional de variáveis

Nota

Ela é equivalente a função subset() do Rbase - caso você esteja acostumado com ela!

deciduous <-  filter(clean, Grupo == "D")
deciduous2 <- subset(clean, Grupo == "D")

Também é possível combinar as condições de filtro!

Nesse caso estamos selecionando as espécies decíduas (D) apenas de Floresta com nitrogênio foliar maior que 2%

deciduous.floresta.highN <- filter(clean, Grupo == "D" & 
                                     Tratamento =="Floresta" &
                                     N >=2)
str(deciduous.floresta.highN)
tibble [6 × 11] (S3: tbl_df/tbl/data.frame)
 $ Tratamento: chr [1:6] "Floresta" "Floresta" "Floresta" "Floresta" ...
 $ especie   : chr [1:6] "AT" "AT" "AT" "GN" ...
 $ Grupo     : chr [1:6] "D" "D" "D" "D" ...
 $ N         : num [1:6] 2.36 2.07 2.03 4.62 3.77 ...
 $ P         : num [1:6] 0.114 0.114 0.121 0.143 0.157 ...
 $ Mg        : num [1:6] 0.15 0.18 0.133 0.247 0.176 ...
 $ K         : num [1:6] 1.197 1.444 0.366 1.263 1.388 ...
 $ Ca        : num [1:6] 0.319 0.413 0.371 0.645 0.266 ...
 $ Al_ppm    : num [1:6] 123 252 206 181 148 ...
 $ area      : num [1:6] 288 262 184 274 385 ...
 $ peso      : num [1:6] 3.63 2.49 2.16 3.92 3.62 ...

Verificar operadores lógicos do R

Operador %in%

Para selecionar vários níveis dentro de uma variável

sp <- filter(clean, especie %in% c("CB", "KC", "QP"))
str(sp)
tibble [27 × 11] (S3: tbl_df/tbl/data.frame)
 $ Tratamento: chr [1:27] "Floresta" "Floresta" "Floresta" "Floresta" ...
 $ especie   : chr [1:27] "CB" "CB" "CB" "KC" ...
 $ Grupo     : chr [1:27] "B" "B" "B" "D" ...
 $ N         : num [1:27] 1.18 1.27 1.55 1.23 1.41 ...
 $ P         : num [1:27] 0.0929 0.0786 0.0714 0.0786 0.1 ...
 $ Mg        : num [1:27] 0.088 0.0788 0.0822 0.1123 0.1307 ...
 $ K         : num [1:27] 0.318 0.233 0.336 0.567 0.459 0.479 0.376 0.934 0.405 0.657 ...
 $ Ca        : num [1:27] 0.315 0.12 0.112 0.311 0.336 ...
 $ Al_ppm    : num [1:27] 45.3 51.8 38.8 155 180.8 ...
 $ area      : num [1:27] 490 312 288 287 145 ...
 $ peso      : num [1:27] 5.6 4.77 5.38 4.78 1.42 ...

Rename

A função rename() é importante para mudar os nomes das variáveis. O nome atual vem antes do nome original. Vamos mudar os nomes para inglês.

Dica!

Quando o nome for espaçado ou tiver caracter especial ou número, deve estar entre o símbolo `

ls(clean)
 [1] "Al_ppm"     "area"       "Ca"         "especie"    "Grupo"     
 [6] "K"          "Mg"         "N"          "P"          "peso"      
[11] "Tratamento"
new <- rename(clean, Vegetation = Tratamento, Species = especie, `Phenological group` = Grupo,
                Al = Al_ppm, 
                `leaf area` = area, `leaf mass` = peso)

ls(new)
 [1] "Al"                 "Ca"                 "K"                 
 [4] "leaf area"          "leaf mass"          "Mg"                
 [7] "N"                  "P"                  "Phenological group"
[10] "Species"            "Vegetation"        

Arrange

A função arrange() permite colocarmos os dados em determinada ordem. Isso é importante principalmente para verificar tendências ou outliers Aqui vamos colocar os dados na ordem do maior valor de Al par ao menor para verificarmos as plantas acumuladoras de alumínio. Vamos usar a função head() para olhar como os dados foram ordenados do maior valor de Al.

acumuladoras <- arrange (new, desc(Al))

head(acumuladoras)
# A tibble: 6 × 11
  Vegetation Species `Phenological group`     N      P     Mg     K    Ca     Al
  <chr>      <chr>   <chr>                <dbl>  <dbl>  <dbl> <dbl> <dbl>  <dbl>
1 Savana     QP      D                    1.40  0.0786 0.0736 0.728 0.398 15012.
2 Savana     QP      D                    1.48  0.0857 0.0812 0.632 0.236 12878.
3 Savana     QP      D                    1.06  0.0714 0.0728 0.893 0.210 12522.
4 Floresta   QP      D                    1.84  0.0714 0.0776 0.376 0.412 12345 
5 Floresta   QP      D                    1.32  0.0786 0.0844 0.405 0.515 11365 
6 Savana     VE      S                    0.754 0.0571 0.0347 0.326 0.196 10975 
# ℹ 2 more variables: `leaf area` <dbl>, `leaf mass` <dbl>

Mais interessante talvez seja ver esse padrão por algum grupo. Para isso arrange() pode ser muito útil.

acumuladoras <- arrange(new, `Phenological group`, desc(Al))
head(acumuladoras)
# A tibble: 6 × 11
  Vegetation Species `Phenological group`     N      P     Mg     K    Ca    Al
  <chr>      <chr>   <chr>                <dbl>  <dbl>  <dbl> <dbl> <dbl> <dbl>
1 Savana     BC      B                     1.56 0.0714 0.222  0.879 0.968  258.
2 Savana     SA      B                     2.08 0.0714 0.0941 0.561 0.221  258.
3 Savana     SA      B                     1.91 0.0643 0.0734 0.313 0.113  252.
4 Savana     BC      B                     1.41 0.0786 0.171  0.814 0.603  239.
5 Savana     SA      B                     1.99 0.0571 0.0704 0.369 0.15   239.
6 Campo      CB      B                     1.56 0.0786 0.160  0.507 0.503  226 
# ℹ 2 more variables: `leaf area` <dbl>, `leaf mass` <dbl>

Mutate

A função mutate() é muito utilizada para diversos objetivos de manipulação. Com ela, podemos:

  1. Transformar classes de objetos
  2. Mudar os nomes de variáveis ou de fatores
  3. Criar novas variáveis
str(new)
tibble [129 × 11] (S3: tbl_df/tbl/data.frame)
 $ Vegetation        : chr [1:129] "Floresta" "Floresta" "Floresta" "Floresta" ...
 $ Species           : chr [1:129] "AT" "AT" "AT" "BC" ...
 $ Phenological group: chr [1:129] "D" "D" "D" "B" ...
 $ N                 : num [1:129] 2.36 2.07 2.03 1.32 1.23 ...
 $ P                 : num [1:129] 0.1143 0.1143 0.1214 0.0643 0.0714 ...
 $ Mg                : num [1:129] 0.15 0.18 0.133 0.159 0.113 ...
 $ K                 : num [1:129] 1.197 1.444 0.366 0.679 0.957 ...
 $ Ca                : num [1:129] 0.319 0.413 0.371 0.576 0.458 ...
 $ Al                : num [1:129] 122.8 251.8 206.5 96.8 103.3 ...
 $ leaf area         : num [1:129] 288 262 184 149 263 ...
 $ leaf mass         : num [1:129] 3.63 2.49 2.16 1.86 4.39 ...
dados.factor <- mutate_if(new, is.character, as.factor) #1
str(dados.factor)
tibble [129 × 11] (S3: tbl_df/tbl/data.frame)
 $ Vegetation        : Factor w/ 3 levels "Campo","Floresta",..: 2 2 2 2 2 2 2 2 2 2 ...
 $ Species           : Factor w/ 15 levels "AT","BC","BS",..: 1 1 1 2 2 2 3 3 3 4 ...
 $ Phenological group: Factor w/ 3 levels "B","D","S": 2 2 2 1 1 1 1 1 1 1 ...
 $ N                 : num [1:129] 2.36 2.07 2.03 1.32 1.23 ...
 $ P                 : num [1:129] 0.1143 0.1143 0.1214 0.0643 0.0714 ...
 $ Mg                : num [1:129] 0.15 0.18 0.133 0.159 0.113 ...
 $ K                 : num [1:129] 1.197 1.444 0.366 0.679 0.957 ...
 $ Ca                : num [1:129] 0.319 0.413 0.371 0.576 0.458 ...
 $ Al                : num [1:129] 122.8 251.8 206.5 96.8 103.3 ...
 $ leaf area         : num [1:129] 288 262 184 149 263 ...
 $ leaf mass         : num [1:129] 3.63 2.49 2.16 1.86 4.39 ...
new.rename <- mutate(dados.factor, `Phenological group` = recode(`Phenological group`, D = "Deciduous",  #2
                                      B = "Semideciduous", S = "Evergreen"),
                Vegetation = recode(Vegetation, Savana = "Savanna", Floresta = "Forest", Campo = "Grassland"))
str(new.rename)
tibble [129 × 11] (S3: tbl_df/tbl/data.frame)
 $ Vegetation        : Factor w/ 3 levels "Grassland","Forest",..: 2 2 2 2 2 2 2 2 2 2 ...
 $ Species           : Factor w/ 15 levels "AT","BC","BS",..: 1 1 1 2 2 2 3 3 3 4 ...
 $ Phenological group: Factor w/ 3 levels "Semideciduous",..: 2 2 2 1 1 1 1 1 1 1 ...
 $ N                 : num [1:129] 2.36 2.07 2.03 1.32 1.23 ...
 $ P                 : num [1:129] 0.1143 0.1143 0.1214 0.0643 0.0714 ...
 $ Mg                : num [1:129] 0.15 0.18 0.133 0.159 0.113 ...
 $ K                 : num [1:129] 1.197 1.444 0.366 0.679 0.957 ...
 $ Ca                : num [1:129] 0.319 0.413 0.371 0.576 0.458 ...
 $ Al                : num [1:129] 122.8 251.8 206.5 96.8 103.3 ...
 $ leaf area         : num [1:129] 288 262 184 149 263 ...
 $ leaf mass         : num [1:129] 3.63 2.49 2.16 1.86 4.39 ...
final <- mutate(new.rename, SLA = (`leaf area`/`leaf mass`), `N:P` = N/P) #3

A função transmute() equivale a mutate para criação de novas variáveis, porém só mantém a coluna da variável criada (não adiciona novas colunas)

final.2 <- transmute(new.rename, SLA = (`leaf area`/`leaf mass`))

If_else

Função muito útil para transformar variáveis junto com o mutate() de acordo com determinada condição, seguindo a mesma lógica da função equivalente no Rbase ifelse(): ifelse(condição, sim, não)

Note

O diferencial é permitir lidar com valores faltantes!

final3 <- mutate(final, classificação = if_else(Al>1000, "acumuladora", "não-acumuladora"))
view(final3)

Case_when

Similar ao if_else(), mas permite mais condições! Perfeita para classificações ou agrupamentos de variáveis.

final4 <- mutate(final, N_level = case_when(
                                  N < 1 ~ "very low",
                                  1 < N & N < 2 ~ "low",
                                  2 < N & N < 3 ~ "high",
                                  N > 3 ~ "very high"))

PIPE

O símbolo %>% conhecido como pipe é usado para unir as funções, podendo ser mentalmente substituído por “depois” (“then”).

Dessa forma, não precisa se referir aos dados que estão sendo utilizados no início de cada função pois o pipe já assume que o produto de uma etapa é o impute da seguinte.

Assim, organizar o seu código aplicando todos os comandos que fizemos acima, mas usando pipe reduz o número de linhas e deixa tudo mais limpo.

Veja as etapas para chegar no dataset final:

final.pipe <- dados %>%
  mutate_if(is.character, as.factor) %>%  #mudar classe dos objetos
  select(-Amostra, -individuo) %>%  # eliminar colunas inuteis
  rename(Vegetation = Tratamento, Species = especie, `Phenological group` = Grupo,
                Al = Al_ppm, 
                `leaf area` = area, `leaf mass` = peso) %>% #renomear variáveis
  mutate(`Phenological group` = recode(`Phenological group`, D = "Deciduous", 
                                      B = "Semideciduous", S = "Evergreen"),
                Vegetation = recode(Vegetation, Savana = "Savanna", 
                                    Floresta = "Forest", Campo = "Grassland")) %>%  # renomear os fatores
  mutate(SLA=(`leaf area`/`leaf mass`), 
         `N:P` = N/P)  #criar novas variáveis 
summary(final.pipe)
     Vegetation    Species       Phenological group       N        
 Grassland:39   AT     : 9   Semideciduous:44       Min.   :0.612  
 Forest   :45   BC     : 9   Deciduous    :45       1st Qu.:1.225  
 Savanna  :45   CB     : 9   Evergreen    :40       Median :1.413  
                DM     : 9                          Mean   :1.704  
                GN     : 9                          3rd Qu.:2.026  
                KC     : 9                          Max.   :4.994  
                (Other):75                                         
       P                 Mg               K                Ca        
 Min.   :0.03570   Min.   :0.0053   Min.   :0.1910   Min.   :0.0725  
 1st Qu.:0.06430   1st Qu.:0.0745   1st Qu.:0.3760   1st Qu.:0.1738  
 Median :0.07140   Median :0.1026   Median :0.5090   Median :0.2727  
 Mean   :0.08012   Mean   :0.1124   Mean   :0.6624   Mean   :0.3319  
 3rd Qu.:0.08570   3rd Qu.:0.1471   3rd Qu.:0.8140   3rd Qu.:0.4584  
 Max.   :0.22860   Max.   :0.2745   Max.   :2.4910   Max.   :0.9681  
                                                                     
       Al            leaf area        leaf mass           SLA        
 Min.   :   19.3   Min.   : 34.34   Min.   :0.2584   Min.   : 31.59  
 1st Qu.:  116.3   1st Qu.:137.17   1st Qu.:1.8373   1st Qu.: 60.18  
 Median :  180.8   Median :192.61   Median :2.4810   Median : 77.10  
 Mean   : 1763.2   Mean   :204.89   Mean   :2.9656   Mean   : 78.71  
 3rd Qu.:  419.5   3rd Qu.:257.68   3rd Qu.:3.8455   3rd Qu.: 94.92  
 Max.   :15012.5   Max.   :573.53   Max.   :9.4754   Max.   :150.00  
                   NA's   :3        NA's   :3        NA's   :3       
      N:P        
 Min.   : 8.653  
 1st Qu.:16.781  
 Median :19.780  
 Mean   :21.896  
 3rd Qu.:24.412  
 Max.   :63.537  
                 
Dica!

Depois que você deixar os seus dados do jeito que você quer, salve novo arquivo de dados manipulados! Da próxima vez que você for usar conjunto da dados você já pode carregar o arquivo modificado e prontinho, sem passar pela etapa de manipulação novamente. Nunca substitua os dados originais! Use a função write.csv() e escreva sempre a extensão (.csv) no arquivo que será salvo.

write.csv(final.pipe, "Dados_manipulados.csv")

Summarise

A função summarise() (ou summarize()) cria um novo dataframe colapsando valores em um sumário. MUITO ÚTIL pra fazer tabelas de médias, desvio padrão, etc. Usualmente utilizamos a função group_by() antes para especificar os grupos. Também pode ser combinada por summarise_all para aplicar a função em todas as variáveis.

medias<- final.pipe %>% summarise(N = mean(N),
                                   P = mean(P))
medias
# A tibble: 1 × 2
      N      P
  <dbl>  <dbl>
1  1.70 0.0801
# Agrupando e aplicando em todas as colunas

medias2 <- final.pipe %>% group_by(Species, Vegetation, `Phenological group`) %>% 
                summarise_all(mean) #médias por colunas
head(medias2)
# A tibble: 6 × 13
# Groups:   Species, Vegetation [6]
  Species Vegetation `Phenological group`     N      P    Mg     K    Ca    Al
  <fct>   <fct>      <fct>                <dbl>  <dbl> <dbl> <dbl> <dbl> <dbl>
1 AT      Grassland  Deciduous             1.79 0.102  0.165 1.72  0.623 239. 
2 AT      Forest     Deciduous             2.15 0.117  0.154 1.00  0.368 194. 
3 AT      Savanna    Deciduous             2.28 0.129  0.213 1.24  0.736 174. 
4 BC      Grassland  Semideciduous         1.05 0.0476 0.108 0.656 0.404 131. 
5 BC      Forest     Semideciduous         1.30 0.0714 0.130 0.795 0.460  86.0
6 BC      Savanna    Semideciduous         1.41 0.0690 0.176 0.843 0.708 232. 
# ℹ 4 more variables: `leaf area` <dbl>, `leaf mass` <dbl>, SLA <dbl>,
#   `N:P` <dbl>

Múltiplas funções

tabela_mean <- final.pipe %>% select(-Species, -`Phenological group`)%>% group_by(Vegetation) %>% 
  summarise_all(mean, na.rm=T)

tabela1 <- final.pipe %>% select(-Species, -`Phenological group`) %>% group_by(Vegetation) %>% summarise_all(.funs = list(mean, sd))

tabela2 <- final.pipe %>% select(-Species, -`Phenological group`) %>% group_by(Vegetation) %>% summarise_all(.funs = list(media = mean, desvio = sd))

tabela3 <- final.pipe %>% select(-Species, -`Phenological group`) %>% group_by(Vegetation) %>% summarise_all(.funs = list(~mean(., na.rm=T), ~sd(., na.rm=T)))

tabela_all2 <- final.pipe %>% group_by(Vegetation) %>% 
  summarise(across(where(is.numeric), list(media=mean, desvio=sd),na.rm=T)) 
Warning: There was 1 warning in `summarise()`.
ℹ In argument: `across(where(is.numeric), list(media = mean, desvio = sd),
  na.rm = T)`.
ℹ In group 1: `Vegetation = Grassland`.
Caused by warning:
! The `...` argument of `across()` is deprecated as of dplyr 1.1.0.
Supply arguments directly to `.fns` through an anonymous function instead.

  # Previously
  across(a:b, mean, na.rm = TRUE)

  # Now
  across(a:b, \(x) mean(x, na.rm = TRUE))

Utilizando as funções do tidyr

O tidyr tem apenas 4 funções principais! Vamos entender elas AGORA!

Pivot_longer (antiga funcão gather())

A funçao pivot_longer() empilha os dados. Ela é útil para arranjar os dados de forma que algum conjunto de variáveis torne-se um fator. Alguns tipos de gráficos (como gráficos de barras e boxplots) utilizam essa estrutura. Também pode ser importante para fazer gráficos separados em facetas, sendo que cada faceta seria relacionada a um fator.

Logicamente, TUDO depende da sua pergunta e do que você quer demostrar!!!

Vamos usar pivot_longer() para juntar os nutrientes em uma única coluna.

nutri <- medias2 %>% select(-`leaf area`, -`leaf mass`, -SLA, -Al, -`N:P`) %>% pivot_longer(4:8, names_to = "Nutriente", values_to ="media") 
head(nutri)
# A tibble: 6 × 5
# Groups:   Species, Vegetation [2]
  Species Vegetation `Phenological group` Nutriente media
  <fct>   <fct>      <fct>                <chr>     <dbl>
1 AT      Grassland  Deciduous            N         1.79 
2 AT      Grassland  Deciduous            P         0.102
3 AT      Grassland  Deciduous            Mg        0.165
4 AT      Grassland  Deciduous            K         1.72 
5 AT      Grassland  Deciduous            Ca        0.623
6 AT      Forest     Deciduous            N         2.15 
boxplot(media~Nutriente, data=nutri)

Pivot_wider (antiga função spread())

A função pivot_wider faz exatamente o oposto da função pivot_longer. Ela espalha os dados, tornando fatores novas variáveis.

Vamos usar o pivot_wider para criar variáveis com os diferentes grupos fenológicos

grupos <- nutri %>% 
  pivot_wider(names_from=Vegetation, values_from = media)

head(grupos)
# A tibble: 6 × 6
# Groups:   Species [2]
  Species `Phenological group` Nutriente Grassland Forest Savanna
  <fct>   <fct>                <chr>         <dbl>  <dbl>   <dbl>
1 AT      Deciduous            N             1.79   2.15    2.28 
2 AT      Deciduous            P             0.102  0.117   0.129
3 AT      Deciduous            Mg            0.165  0.154   0.213
4 AT      Deciduous            K             1.72   1.00    1.24 
5 AT      Deciduous            Ca            0.623  0.368   0.736
6 BC      Semideciduous        N             1.05   1.30    1.41 

Unite

A função unite junta, como o próprio nome diz, duas ou mais colunas em uma só. Vamos juntar os fatores para criar uma variável de interação com grupo e tratamento, especificando um separador, no caso _ .

inter <- medias2 %>% unite("Interaction", `Phenological group`, Vegetation, sep= "_")
head(inter)
# A tibble: 6 × 12
# Groups:   Species [2]
  Species Interaction               N      P    Mg     K    Ca    Al `leaf area`
  <fct>   <chr>                 <dbl>  <dbl> <dbl> <dbl> <dbl> <dbl>       <dbl>
1 AT      Deciduous_Grassland    1.79 0.102  0.165 1.72  0.623 239.         238.
2 AT      Deciduous_Forest       2.15 0.117  0.154 1.00  0.368 194.         245.
3 AT      Deciduous_Savanna      2.28 0.129  0.213 1.24  0.736 174.         368.
4 BC      Semideciduous_Grassl…  1.05 0.0476 0.108 0.656 0.404 131.         244.
5 BC      Semideciduous_Forest   1.30 0.0714 0.130 0.795 0.460  86.0        197.
6 BC      Semideciduous_Savanna  1.41 0.0690 0.176 0.843 0.708 232.         324.
# ℹ 3 more variables: `leaf mass` <dbl>, SLA <dbl>, `N:P` <dbl>

Separate

A função separate faz o oposto da função unite, separando as colunas em 1 ou mais colunas. Vamos demostrar de algumas formas:

  1. Separando as variáveis que acabamos de juntar no exemplo anterior

  2. Separando as iniciais da variável espécie entre a inicial do gênero e a inicial do epípeto específico,

inter %>% separate(Interaction, into = c("Grupo", "Tipo"), sep = "_")
# A tibble: 44 × 13
# Groups:   Species [15]
   Species Grupo         Tipo       N      P    Mg     K    Ca    Al `leaf area`
   <fct>   <chr>         <chr>  <dbl>  <dbl> <dbl> <dbl> <dbl> <dbl>       <dbl>
 1 AT      Deciduous     Grass…  1.79 0.102  0.165 1.72  0.623 239.        238. 
 2 AT      Deciduous     Forest  2.15 0.117  0.154 1.00  0.368 194.        245. 
 3 AT      Deciduous     Savan…  2.28 0.129  0.213 1.24  0.736 174.        368. 
 4 BC      Semideciduous Grass…  1.05 0.0476 0.108 0.656 0.404 131.        244. 
 5 BC      Semideciduous Forest  1.30 0.0714 0.130 0.795 0.460  86.0       197. 
 6 BC      Semideciduous Savan…  1.41 0.0690 0.176 0.843 0.708 232.        324. 
 7 BS      Semideciduous Grass…  1.25 0.0643 0.161 0.610 0.480 103.        125. 
 8 BS      Semideciduous Forest  1.30 0.0833 0.141 0.464 0.543  96.9       140. 
 9 BS      Semideciduous Savan…  1.28 0.0691 0.143 0.620 0.668 164.         50.1
10 CB      Semideciduous Grass…  1.46 0.0786 0.157 0.479 0.455 187.        394. 
# ℹ 34 more rows
# ℹ 3 more variables: `leaf mass` <dbl>, SLA <dbl>, `N:P` <dbl>
inter %>% separate(Species, into = c("Genero", "Epípeto"), sep = 1)
# A tibble: 44 × 13
   Genero Epípeto Interaction       N      P    Mg     K    Ca    Al `leaf area`
   <chr>  <chr>   <chr>         <dbl>  <dbl> <dbl> <dbl> <dbl> <dbl>       <dbl>
 1 A      T       Deciduous_Gr…  1.79 0.102  0.165 1.72  0.623 239.        238. 
 2 A      T       Deciduous_Fo…  2.15 0.117  0.154 1.00  0.368 194.        245. 
 3 A      T       Deciduous_Sa…  2.28 0.129  0.213 1.24  0.736 174.        368. 
 4 B      C       Semideciduou…  1.05 0.0476 0.108 0.656 0.404 131.        244. 
 5 B      C       Semideciduou…  1.30 0.0714 0.130 0.795 0.460  86.0       197. 
 6 B      C       Semideciduou…  1.41 0.0690 0.176 0.843 0.708 232.        324. 
 7 B      S       Semideciduou…  1.25 0.0643 0.161 0.610 0.480 103.        125. 
 8 B      S       Semideciduou…  1.30 0.0833 0.141 0.464 0.543  96.9       140. 
 9 B      S       Semideciduou…  1.28 0.0691 0.143 0.620 0.668 164.         50.1
10 C      B       Semideciduou…  1.46 0.0786 0.157 0.479 0.455 187.        394. 
# ℹ 34 more rows
# ℹ 3 more variables: `leaf mass` <dbl>, SLA <dbl>, `N:P` <dbl>

Leitura complementar

FIM