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()!
library(tidyverse)
Warning: package 'tidyverse' was built under R version 4.0.5
v ggplot2 3.3.5 v purrr 0.3.4
v tibble 3.1.3 v dplyr 1.0.7
v tidyr 1.1.3 v stringr 1.4.0
v readr 2.0.1 v forcats 0.5.1
Warning: package 'ggplot2' was built under R version 4.0.5
Warning: package 'tibble' was built under R version 4.0.5
Warning: package 'tidyr' was built under R version 4.0.5
Warning: package 'readr' was built under R version 4.0.5
Warning: package 'dplyr' was built under R version 4.0.5
Warning: package 'forcats' was built under R version 4.0.5
-- Conflicts ------------------------------------------ tidyverse_conflicts() --
x dplyr::filter() masks stats::filter()
x dplyr::lag() masks stats::lag()
# 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
i Use `spec()` to retrieve the full column specification for this data.
i Specify the column types or set `show_col_types = FALSE` to quiet this message.
str(dados)
spec_tbl_df [129 x 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:
Selecionar apenas as variáveis categóricas
Excluir variávies não úteis
Condicional, no caso se a variável for numérica usando is.numeric
Selecionar variávels com alguma característica comum utilizando starts_with() ou ends_with()
tibble [129 x 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 x 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
# ... with 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
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.
# A tibble: 6 x 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
# ... with 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:
Transformar classes de objetos
Mudar os nomes de variáveis ou de fatores
Criar novas variáveis
A função transform() também cria novas variávies de forma equivalente, mas observe a diferença nos nomes das variáveis
str(new)
tibble [129 x 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 ...
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 objetosselect(-Amostra, -individuo) %>%# eliminar colunas inuteisrename(Vegetation = Tratamento, Species = especie, `Phenological group`= Grupo,Al = Al_ppm, `leaf area`= area, `leaf mass`= peso) %>%#renomear variáveismutate(`Phenological group`=recode(`Phenological group`, D ="Deciduous", B ="Semideciduous", S ="Evergreen"),Vegetation =recode(Vegetation, Savana ="Savanna", Floresta ="Forest", Campo ="Grassland")) %>%# renomear os fatoresmutate(SLA=(`leaf area`/`leaf mass`), `N:P`= N/P) #criar novas variáveissummary(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
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.
# Agrupando e aplicando em todas as colunasmedias2 <- final.pipe %>%group_by(Species, Vegetation, `Phenological group`) %>%summarise_all(mean) #médias por colunashead(medias2)
# A tibble: 6 x 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.
# ... with 4 more variables: leaf area <dbl>, leaf mass <dbl>, SLA <dbl>,
# N:P <dbl>
Stringr é outro pacote do tidyverse que lida com strings - nomes!. Útil para manipular planilhas com variáveis characteres. Caso vc se interesse em se aprofundar nesse pacote, tem um vídeo muito útil feito pelo pessoal da UEM aqui
Tibble é um pacote do tidyverse que transforma os dados em um novo tipo de data frame - um tibble. Muito útil para quem trabalha com datasets muito grandes porque é um dataframe simplificado.
$N
mean sd
1.7044806 0.8685233
$P
mean sd
0.08012093 0.03193007
$Mg
mean sd
0.11240155 0.05033641
$K
mean sd
0.6624186 0.4012569
$Ca
mean sd
0.3318806 0.1980531
$Al
mean sd
1763.154 3430.080
apply(final.pipe[4:9], 2, sum.table)
N P Mg K Ca Al
mean 1.7044806 0.08012093 0.11240155 0.6624186 0.3318806 1763.154
sd 0.8685233 0.03193007 0.05033641 0.4012569 0.1980531 3430.080
sapply(a[4:9], sum.table)
N P Mg K Ca Al
mean 1.7044806 0.08012093 0.11240155 0.6624186 0.3318806 1763.154
sd 0.8685233 0.03193007 0.05033641 0.4012569 0.1980531 3430.080
tapply(final.pipe$N, final.pipe$Vegetation, sum.table) #divide em grupos: tapply(X, INDEX, FUN = NULL)
$Grassland
mean sd
1.5776410 0.6262919
$Forest
mean sd
1.6572667 0.7384168
$Savanna
mean sd
1.861622 1.126328
tibble [3 x 21] (S3: tbl_df/tbl/data.frame)
$ Vegetation : Factor w/ 3 levels "Grassland","Forest",..: 1 2 3
$ mean_N : num [1:3] 1.58 1.66 1.86
$ sd_N : num [1:3] 0.626 0.738 1.126
$ mean_P : num [1:3] 0.0747 0.0811 0.0838
$ sd_P : num [1:3] 0.0238 0.026 0.0419
$ mean_Mg : num [1:3] 0.115 0.11 0.112
$ sd_Mg : num [1:3] 0.0413 0.0442 0.0627
$ mean_K : num [1:3] 0.706 0.591 0.696
$ sd_K : num [1:3] 0.417 0.363 0.422
$ mean_Ca : num [1:3] 0.343 0.326 0.328
$ sd_Ca : num [1:3] 0.18 0.167 0.241
$ mean_Al : num [1:3] 1157 1922 2130
$ sd_Al : num [1:3] 2243 3594 4059
$ mean_leaf area: num [1:3] 218 217 180
$ sd_leaf area : num [1:3] 74.5 75.6 121.5
$ mean_leaf mass: num [1:3] 3.57 3.01 2.36
$ sd_leaf mass : num [1:3] 1.89 1.33 1.93
$ mean_SLA : num [1:3] 67.6 78.4 89.3
$ sd_SLA : num [1:3] 18.6 24.1 27.3
$ mean_N:P : num [1:3] 21.5 20.6 23.5
$ sd_N:P : num [1:3] 6.09 5.35 12.51
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.
# A tibble: 6 x 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 x 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 x 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_Grassland 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.
# ... with 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:
Separando as variáveis que acabamos de juntar no exemplo anterior
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 x 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 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 Grassland 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.
7 BS Semideciduous Grassland 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 Savanna 1.28 0.0691 0.143 0.620 0.668 164. 50.1
10 CB Semideciduous Grassland 1.46 0.0786 0.157 0.479 0.455 187. 394.
# ... with 34 more rows, and 3 more variables: leaf mass <dbl>, SLA <dbl>,
# N:P <dbl>
inter %>%separate(Species, into =c("Genero", "Epípeto"), sep =1)
# A tibble: 44 x 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.
# ... with 34 more rows, and 3 more variables: leaf mass <dbl>, SLA <dbl>,
# N:P <dbl>