Essa é uma pequena análise explorando os dados de espécies nativas da flora brasileira. Esta é a primeira parte de uma série de três análises integrando dados do projeto Flora 2020 do Jardim Botânico do Rio de Janeiro (JBRJ), Global Biodiversity Information Facility (GBIF) e a Lista Vermelha da IUCN. O objetivo dessa série é analisar algumas informações jogadas em minha nuvem de “coisas para explorar da flora” que não tive tempo enquanto ainda trabalhando na área, ao passo que treino/refino algumas técnicas de análise de dados e estatística em geral e ainda guardo alguns códigos e pipelines úteis para outras instâncias.

Esta primeira parte visa extrair, manipular e limpar dados da flora 2020, além de constuir algumas visualizações dos dados. Uma segunda parte, mais voltada para análises estatísticas e desenho experimental já está em andamento e uma terceira já está planejada para ser conduzida em seguida. Todas estas análises estão sob constante revisão, sofrendo constantes alterações

Estou usando exclusivamente R nessa série.

Esta análise está dividida em duas seções:

  1. Extração, limpeza e compilação de dados: Aqui extraio os dados do projeto Flora 2020 direto do IPT do JBRJ, observo a estrutura dos dados e formato/limpo eles da maneira que preciso para analisá-los da forma que pretendo. Essa parte da análise é relativamente extensa e técnica, sem análises de dados ou visualizações. Em linhas gerais, executo as atividades abaixo:
    • Extração dos dados da flora 2020
    • Compilação de dados em um único data frame
    • Filtro de espécies
    • Limpeza de dados
    • Formatação de variáveis
    • Parsing
  2. Análise e visualização de dados: Aqui, analiso o data frame unificado criado na etapa anterior, ploto algumas visuzalizações e mato a curiosidade sobre alguns aspectos dos dados. Algumas análises feitas:
    • Distribuição dos anos de descrição das espécies
    • Descrições anuais dos grandes grupos taxonômicos
    • Formas de vida e tipo de vegetação mais frequentes

Principais pacotes utilizados:

  • tidyverse: Conjunto de pacotes com ferramentas de análise, transformação e visualização de dados.
  • lubridate: Manipulação de datas e hora´.
  • patchwork: Combinar gráficos separados de maneira simples.
  • ggrepel: Arranjo organizado de labels em plots.
  • forcats: Manipulação mais intuitiva de variáveis categóricas.
  • jsonlite: Parsing de entradas json.
  • PNWColors: Paleta de cores.
  • ggExtra: Funções para aprimorar o ggplot2.
  • cowplot: Plotar gráficos em grid.

Ademais, escrevi algumas funções que auxiliaram na transformação desses dados, algumas explicitei no próprio documento, outras mais extensas não, mas todas podem ser encontradas no repositório do projeto em meu github.

1 Extração, limpeza e compilação de dados


Os dados utilizados se referem àqueles gerados pelo projeto Flora 2020 do JBRJ. O principal objetivo desse projeto é catalogar a maior quantidade de dados possíveis da flora brasileira, no âmbito da “Estratégia Global para Conservação de Plantas (GSPC)”. Dentre os dados disponíveis, quero compilar e explorar àqueles pertencentes à quatro grandes grupos:

  • Dados de descrição: anos em que as espécies foram descritas e os autores que as descreveram.
  • Dados ecológicos e de distribuição: em que tipos de ambiente as espécies ocorrem e em quais estados brasileiros.
  • Dados vernaculares: nomes populares dados às espécies.

Essas informações encontram-se armazenadas em uma série de arquivos organizados como tabelas interrelacionais. Se encontram no formato Darwin Core (DwC-A), um padrão de formatação de dados da biodiversidade. O projeto Flora 2020 armazena informações para todos níveis taxonômicos, mas aqui pretendo analisar apenas o nível de espécie.

1.1 Estrutura dos dados


Antes de mais nada, vou carregar todos pacotes e funções que irei utilizar daqui em diante:

# primeiro os pacotes já citados:
library(tidyverse) 
library(lubridate)
library(patchwork) 
library(ggrepel) 
library(forcats) 
library(PNWColors)
library(jsonlite)
library(ggExtra)
library(plotly)
library(cowplot)
# funções que eu escrevi para a analise
source("scripts/flora_2020_analysis_functions.R")
pal=pnw_palette("Bay",5, type = "discrete")

Agora é baixar os dados direto do ipt, que estão em um zip:

rl <- 'http://ipt.jbrj.gov.br/jbrj/archive.do?r=lista_especies_flora_brasil&v=393.224' # url do aquivo
download.file(url, destfile = "data.zip", mode="wb") # download
unzip(zipfile = "data.zip",exdir = "data") # extração na pasta "data"

As informações que busco estão nos arquivos .txt do DwC-A:

grep(".txt",list.files("data/"),value=TRUE)
## [1] "distribution.txt"         "reference.txt"           
## [3] "resourcerelationship.txt" "speciesprofile.txt"      
## [5] "taxon.txt"                "typesandspecimen.txt"    
## [7] "vernacularname.txt"

Quero compilar informações de 5 arquivos:

  1. taxon.txt: contém as informações mais básicas que preciso para começar a análise, como as informações taxonômicas das entradas e os autores das descrições. Lembrando que os dados desse arquivo se aplicam a todos níveis taxonômicos contemplados no projeto (e.g. reino e gênero).

  2. reference.txt: contém informações relativas à descrição dos taxa (e.g. ano e autor).

  3. distribution.txt: informa se os taxa são endêmicos ou não e em que domínios fitogeográficos ou estados brasileiros eles ocorrem.

  4. specieprofile.txt: contém informações acerca da forma de vida, habitat e tipo de vegetação de ocorrência dos taxa.

  5. vernacular.txt: contém os nomes populares das espécies.

Não vou usar os demais arquivos, typesandspecimen.txt e resourcerelationship.txt, pois eles se referem a dados não utilizados em minhas análises. Sempre vale lembrar também que a informação que busco nessa análise muito provavelmente não existe para todas espécies da amostra.

Vou então ler todos esses arquivos:

taxon <- read_delim(file="data/taxon.txt", delim = "\t")
distribution <- read_delim(file="data/distribution.txt", delim = "\t")   
references <- read_delim("data/reference.txt", delim = "\t")
vernacular <- read_delim("data/vernacularname.txt", delim = "\t")
profile <- read_delim("data/speciesprofile.txt", delim = "\t")

O que quero fazer em seguida é compilar apenas as informações que preciso de cada um desses arquivos, armazenando tudo em um único data frame que vou chamar de df_master.

1.2 Filtrando espécies nativas


Para esta análise, quero trabalhar apenas com espécies nativas e sem problemas nomenclaturais de qualquer tipo (não são sinônimos, espécies naturalizadas ou exóticas/invasivas, nem representam nomes em desuso). Para fazer isso vou começar filtrando as colunas taxonomicStatus, nomenclaturalStatus e taxonRank da tabela taxon.

A coluna taxonomicStatus indica se um registro se refere a um nome aceito ou sinônimo:

unique(taxon$taxonomicStatus)
## [1] "NOME_ACEITO" "SINONIMO"    NA

Já a coluna nomenclaturalStatus indica se o nome em questão é correto ou se existe algum tipo de problema associado a ele:

unique(taxon$nomenclaturalStatus)
##  [1] "NOME_CORRETO"                    NA                               
##  [3] "NOME_LEGITIMO_MAS_INCORRETO"     "NOME_CORRETO_VIA_CONSERVACAO"   
##  [5] "VARIANTE_ORTOGRAFICA"            "NOME_ILEGITIMO"                 
##  [7] "NOME_NAO_EFETIVAMENTE_PUBLICADO" "NOME_NAO_VALIDAMENTE_PUBLICADO" 
##  [9] "NOME_MAL_APLICADO"               "NOME_REJEITADO"                 
## [11] "NOME_APLICACAO_INCERTA"

Um taxon pode não ter tido seu nome publicado ainda ou pode ter sido catalogado de forma incorreta por algum motivo. Vou seguir mantendo apenas espécies que tem nomes corretos sem qualquer tipo de problema.

Finalmente, a tabela taxonRank indica o nível taxonômico do registro:

unique(taxon$taxonRank)
##  [1] "ORDEM"       "FAMILIA"     "GENERO"      "ESPECIE"     "VARIEDADE"  
##  [6] "SUB_ESPECIE" "CLASSE"      "TRIBO"       "SUB_FAMILIA" "DIVISAO"    
## [11] "FORMA"

Faço então todos filtros que preciso e mantenho na tabela taxon apenas as espécies que seguem meus critérios:

taxon <- taxon %>% 
  filter(taxonomicStatus == "NOME_ACEITO", # apenas nomes aceitos
         nomenclaturalStatus == "NOME_CORRETO", # apenas nomes corretos
         taxonRank == "ESPECIE") # apenas nomes que se referem a espécies

Ainda assim, ainda não filtrei as espécies nativas da amostra, dado que essa informação não está contida na tabela taxon, pois está na arquivo distribution, especificamente na coluna establishmentMeans. Para filtrar isso posso usar os id´s da tabela taxon, que agora contém apenas as espécies com nome correto:

# filtro entradas nativas na tabela distribution
distribution <- distribution %>% filter(establishmentMeans == "NATIVA") 

# extraio as id´s que se referem à espécies nativas
ids_native <- unique(distribution$id) 

# filtro tabela taxon novamente, mantendo apenas espécies nativas
taxon <- taxon %>% filter(id %in% ids_native)

A tabela taxon agora está do jeito que quero, apenas com espécies nativas e com nomes livres de problemas. Essa tabela vai formar a base do df_master, então, a partir dela, vou selecionar apenas minhas variáveis de interesse e incrementar aos poucos com novas informações das demais tabelas que ainda me resta analisar:

# criando df_master a partir das variáveis de interesse da colunas taxon

df_master <- taxon %>% 
              select(id, # id das especies
                     scientificName, # nome científico
                     higherClassification, # backbone taxonomico
                     family) # familia

Vale dar uma olhada geral na estrutura da tabela:

glimpse(df_master)
## Rows: 38,079
## Columns: 4
## $ id                   <dbl> 264, 280, 285, 301, 315, 319, 342, 343, 439, 440…
## $ scientificName       <chr> "Adiscanthus fusciflorus Ducke", "Andreadoxa fla…
## $ higherClassification <chr> "Flora;Angiospermas;Rutaceae A.Juss.;Adiscanthus…
## $ family               <chr> "Rutaceae", "Rutaceae", "Rutaceae", "Rutaceae", …

A tabela contém a informação de 38079 espécies nativas da flora brasileira, mas ainda falta informação a ser compilada.

1.3 Compilando os dados restantes


Agora vou extrair as demais informações seguindo a lógica utilizada na tabela taxon, mas usando a função match. Especificamente, quero puxar os dados abaixo das espécies:

  • Ano de descrição
  • Autor da descrição
  • Domínios fitogeográficos de ocorrência
  • Estados da Federação de ocorrência
  • Formas de vida
  • Tipos de vegetação de ocorrência
  • Nomes populares

1.3.1 Autores e anos de descrição das espécies


A tabela references contém o ano de descrição e autoria das mesmas para as espécies, respectivamente nas colunas date e creator. Ao incluir essas informações no df_master, vou criar nomes mais intuitivos para as colunas:

ids_master <- df_master[["id"]] # pego as ids das espécies contidas no df_master

# nova coluna criada com os anos de descrição das espécies

df_master[["desc_year"]] <- references$date[match(ids_master,references$id)] 

# mesma coisa com os autores

df_master[['descriptor']] <- references$creator[match(ids_master,references$id)] 

Antes de seguir em frente, já vou limpar a coluna de datas que apresenta alguns problemas:

unique(df_master$desc_year)[250:300] 
##  [1] "1994/1995"                              
##  [2] "107"                                    
##  [3] "1809"                                   
##  [4] "2018"                                   
##  [5] "147"                                    
##  [6] "1868-70"                                
##  [7] "393"                                    
##  [8] "187"                                    
##  [9] "2019"                                   
## [10] "1831-1834"                              
## [11] "1785"                                   
## [12] "1796"                                   
## [13] "1814"                                   
## [14] "1794"                                   
## [15] "189"                                    
## [16] "194"                                    
## [17] "1989/1990"                              
## [18] "1764"                                   
## [19] "1071"                                   
## [20] "216"                                    
## [21] "1967-1969"                              
## [22] "1886-1888"                              
## [23] "1772"                                   
## [24] "doi:10.1594/PANGAEA.85167  4196946_35_0"
## [25] "285"                                    
## [26] "no prelo"                               
## [27] "3013"                                   
## [28] "1969."                                  
## [29] "1992."                                  
## [30] "1828."                                  
## [31] "2006."                                  
## [32] "1991."                                  
## [33] "2010."                                  
## [34] "212"                                    
## [35] "1"                                      
## [36] "213"                                    
## [37] "454"                                    
## [38] "461"                                    
## [39] "60"                                     
## [40] "262"                                    
## [41] "35"                                     
## [42] "191"                                    
## [43] "2994"                                   
## [44] "467"                                    
## [45] "906"                                    
## [46] "199"                                    
## [47] "1793"                                   
## [48] "2020"                                   
## [49] NA                                       
## [50] NA                                       
## [51] NA

Vou ser um pouco conservador na minha abordagem e eliminar tudo que não tem mais de quatro caracteres (já que a coluna está formatada como string):

# função para limpar as datas:
  # se data for NA, mantem como NA
  # se data tiver quatro caracteres, mantem data
  # se não, retorna NA
clean_dates <- function(x){ 
  if(is.na(x)){return(NA) 
    break
  } 
  if (nchar(x) == 4){return(x)}
  else{return(NA)}} 

# vou aplicar a função para a coluna toda e converter o tipo para numerico
  # tipo numerico vai converter para NA o que tiver letra dentre os quatro char

df_master[['desc_year']] <- df_master[['desc_year']] %>% # coluna
                              map(clean_dates) %>%  # aplicar função
                              as.numeric() # deixar como tipo numerico

Vou dar uma olhada nas estatísticas sumarizadas da coluna:

summary(df_master[['desc_year']])
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
##    1071    1893    1976    1948    2003    3013   14661

O mínimo e o máximo ainda estão bem esquisitos, vou manter apenas datas que se encontram em um intervalo de tempo razoável: entre 1700 (pouco antes do estabelecimento do sistema lineniano) e 2020. O resto vou converter para NA.

year_fix <- function(x){
  if (is.na(x)){return(NA)} # se o ano é NA, retorna NA
  if (x<1700 || x>2020){return(NA)}else{return(x)} # valores fora do intervalo retornam NA
}

# recriando coluna aplicando a função à coluna existente

df_master <- df_master %>% mutate(desc_year = modify(df_master[['desc_year']],year_fix))

Os valores agora parecem fazer mais sentido:

sort(unique(df_master[['desc_year']]))
##   [1] 1752 1753 1755 1756 1759 1760 1762 1763 1764 1765 1766 1767 1768 1771 1772
##  [16] 1773 1775 1781 1782 1783 1784 1785 1786 1788 1789 1791 1792 1793 1794 1796
##  [31] 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811
##  [46] 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826
##  [61] 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841
##  [76] 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856
##  [91] 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871
## [106] 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886
## [121] 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901
## [136] 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916
## [151] 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931
## [166] 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946
## [181] 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961
## [196] 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976
## [211] 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991
## [226] 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006
## [241] 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020

1.3.2 Estados da federação, endemismo, domínio fitogeográfico, informações ecológicas e vernaculares


Agora vou adicionar as informações da tabela distribution. A coluna location_id contém a informação acerca dos estados no Brasil onde as espécies ocorrem. Cada id é repetido por número estado de ocorrência:

distribution %>% filter(id == 264)

Essa espécie ocorre no Pará, Amazonas e Acre. Vou inserir essas informações para as espécies no df_master de modo elas fiquem agrupadas em uma única string, usando um separador:

# nessa função, indico qual o separador que vou usar depois de especificar uma id (x), 
# coluna e tabela.

collapse_column <- function(x,column,df,split_character=";"){ 
  df_temp <- df %>% filter(id == x) 
  if (length(rownames(df_temp)) == 0){return(NA)} else { 
    output <- paste(df_temp[[column]],collapse = split_character) 
    return(output)
  }
}


# crio uma nova coluna 'states' com as informações de estado de ocorrência

df_master[['states']] <- map(ids_master,collapse_column,column="locationID",df=distribution) %>% 
                        gsub("BR-","",.) # removendo o prefixo para ficar mais limpo

E a coluna fica com uma cara assim:

df_master['states'] %>% slice(1:10) 

Agora vou extrair as informações de domínios de ocorrência e endemismo, ambas contidas nas colunas occurrenceRemarks, ainda da tabela distribution. Essas informações estão armazenadas no formato json:

distribution$occurrenceRemarks[5000]
## [1] "{\"endemism\":\"Não endemica\",\"phytogeographicDomain\":[\"Amazônia\"]}"

Vou extrair nesse formato mesmo e fazer o parsing mais adiante:

df_master['distribution']<-distribution$occurrenceRemarks[match(ids_master,distribution$id)]

As informações ecológicas estão armazenadas de maneira semelhante, na tabela profile, em uma coluna de nome não muito intuitivo: lifeForm. Vou incluir esses dados direto em uma coluna do df_master e fazer o parsing depois.

df_master['profile'] <- profile$lifeForm[match(ids_master,profile$id)]

Já os nomes vernaculares das espécies encontram-se na coluna vernacularName da tabela vernacular, armazenados da mesma forma que os estados de ocorrência, então vou usar a função que utilizei no caso dos estados, gerando uma nova coluna no df_master chamada vernacular_name:

df_master['vernacular_name'] <-  
  map(ids_master,collapse_column,
  column="vernacularName",df=vernacular) %>% 
  unlist() 

1.3.3 Parsing


A maior parte dos dados que preciso já está no df_master, mas ainda preciso fazer o parsing daquelas colunas no formato json. Vou chamar uma função que fiz para lidar com isso, o que essa função faz é quebrar em colunas a informação contida nos json, por exemplo, isso aqui:

df_master$distribution[1507:1508]
## [1] "{\"endemism\":\"Endemica\",\"phytogeographicDomain\":[\"Mata Atlântica\"]}"
## [2] "{\"endemism\":\"Endemica\",\"phytogeographicDomain\":[\"Mata Atlântica\"]}"

Toma o formato abaixo, onde as chaves se tornam colunas com a informação pertinente:

json_parser(df_master$distribution[1507:1508])

Então uso a função nas colunas inteiras que contém informação como JSON e este problema está resolvido:

# parsing da coluna distribution 
  # cada chave vai ser uma coluna nova
df_master <- json_parser(df_master$distribution) %>% 
              bind_cols(df_master) %>% # incluo a informação no df_master
              select(-distribution) # remove a coluna com os JSON, agora obsoleta

# mesma coisa com a coluna profile
df_master <- json_parser(df_master$profile) %>% 
              bind_cols(df_master) %>% 
              select(-profile,-habitat) # alem de remover a coluna obsoleta, tirei a coluna da chave habitat
# que não vai ser utilizada na análise

Essa operação criou três novas colunas no df_master: lifeForm e vegetationType, que vieram da tabela distribution e as colunas endemism e phytogeographicDomain que vieram da tabela profile:

head(df_master)

Ainda me resta extrair apenas o que quero da coluna higherClassification, que contém informações taxonômicas das espécies e está formatada dessa maneira:

head(df_master[["higherClassification"]])
## [1] "Flora;Angiospermas;Rutaceae A.Juss.;Adiscanthus Ducke;Adiscanthus fusciflorus Ducke"                      
## [2] "Flora;Angiospermas;Rutaceae A.Juss.;Andreadoxa Kallunki;Andreadoxa flava Kallunki"                        
## [3] "Flora;Angiospermas;Rutaceae A.Juss.;Angostura Roem. & Schult.;Angostura bracteata (Nees & Mart.) Kallunki"
## [4] "Flora;Angiospermas;Rutaceae A.Juss.;Angostura Roem. & Schult.;Angostura longiflora (K.Krause) Kallunki"   
## [5] "Flora;Angiospermas;Rutaceae A.Juss.;Angostura Roem. & Schult.;Angostura quinquefolia Kallunki"            
## [6] "Flora;Angiospermas;Rutaceae A.Juss.;Angostura Roem. & Schult.;Angostura simplex Kallunki"

Eu quero extrair apenas a informação referente ao segundo grupo taxonômico mais inclusivo no qual cada espécie pertence, o segundo elemento entre os separadores:

# função para extrair determinado elemento de determinada string com determinado separador

function_split_pluck <- function(string,split=";",pluck=2){
  string %>%  
  strsplit(split = split) %>%
  unlist() %>% 
  pluck(pluck) 
}

# aplico a função na coluna e crio uma nova coluna apenas com o grande grupo taxonomico

df_master['major_group'] <- map_chr(df_master$higherClassification, function_split_pluck)

df_master <- df_master %>% select(-higherClassification) # removo a coluna obsoleta

1.3.4 Ajustes finais


A maior parte dos dados já está pronta, mas a tabela ainda precisa de uns ajustes finais. Por exemplo, seria melhor remover acentos de algumas colunas do df_master, dado que eles podem ser problemáticos para algumas visualizações:

df_master <- df_master %>% 
        # vou selecionar apenas as colunas que quero formatar
        mutate_at(c("lifeForm","endemism","vernacular_name","major_group"),
                  iconv,
                  from="UTF-8",to="ASCII//TRANSLIT") # iconv remove os acentos dessas colunas 

Também vou reordenar e renomear as colunas de maneira mais intuitiva:

df_master <- df_master %>% 
              select(id,major_group,
                     family,scientificName,
                     desc_year,descriptor,
                     lifeForm,vegetationType,
                     endemism,phytogeographicDomain,
                     states,vernacular_name) %>%
              rename(scientific_name=scientificName,
                                   phytogeographic_domains=phytogeographicDomain,
                                   life_form=lifeForm,
                                   vegetation_type=vegetationType)

Agora vale uma reolhada na estrutura do data frame para checar os tipos das variáveis:

glimpse(df_master)
## Rows: 38,079
## Columns: 12
## $ id                      <dbl> 264, 280, 285, 301, 315, 319, 342, 343, 439, …
## $ major_group             <chr> "Angiospermas", "Angiospermas", "Angiospermas…
## $ family                  <chr> "Rutaceae", "Rutaceae", "Rutaceae", "Rutaceae…
## $ scientific_name         <chr> "Adiscanthus fusciflorus Ducke", "Andreadoxa …
## $ desc_year               <dbl> 1922, 1998, 1998, 1998, 1998, 1998, 1998, 189…
## $ descriptor              <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, "…
## $ life_form               <chr> "Arvore", "Arvore", "Arvore", "Arvore", "Arvo…
## $ vegetation_type         <chr> "Campinarana;Floresta Ombrófila (= Floresta P…
## $ endemism                <chr> "Nao endemica", "Endemica", "Endemica", "Nao …
## $ phytogeographic_domains <chr> "Amazônia", "Mata Atlântica", "Mata Atlântica…
## $ states                  <chr> "PA;AM;AC", "BA", "RJ;ES;BA", "AC;MT", "MA;PA…
## $ vernacular_name         <chr> NA, NA, "gramirim-cafe", "matapira;mata rabuj…

A maior parte das colunas está formatada como string, embora a maioria seja constituída de variáveis categóricas, vou converter algumas que não contém separadores e que não são números para fatores:

glimpse(
  df_master <- df_master %>% mutate_at(c("life_form", 
                          "endemism",
                          "scientific_name",
                          "family"), as.factor)
  )
## Rows: 38,079
## Columns: 12
## $ id                      <dbl> 264, 280, 285, 301, 315, 319, 342, 343, 439, …
## $ major_group             <chr> "Angiospermas", "Angiospermas", "Angiospermas…
## $ family                  <fct> Rutaceae, Rutaceae, Rutaceae, Rutaceae, Rutac…
## $ scientific_name         <fct> Adiscanthus fusciflorus Ducke, Andreadoxa fla…
## $ desc_year               <dbl> 1922, 1998, 1998, 1998, 1998, 1998, 1998, 189…
## $ descriptor              <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, "…
## $ life_form               <fct> Arvore, Arvore, Arvore, Arvore, Arvore, Arvor…
## $ vegetation_type         <chr> "Campinarana;Floresta Ombrófila (= Floresta P…
## $ endemism                <fct> Nao endemica, Endemica, Endemica, Nao endemic…
## $ phytogeographic_domains <chr> "Amazônia", "Mata Atlântica", "Mata Atlântica…
## $ states                  <chr> "PA;AM;AC", "BA", "RJ;ES;BA", "AC;MT", "MA;PA…
## $ vernacular_name         <chr> NA, NA, "gramirim-cafe", "matapira;mata rabuj…

2 Análise e visualização dos dados


As variáveis que quero investigar podem ser divididas em 4 grupos:

  1. Temporais: ano e autor da descrição das espécies
  2. Geográficas: estados e biomas de ocorrência
  3. Ecológicas: formas de vida e tipos de vegetação
  4. Vernaculares: nomes populares das espécies

Com todas já compiladas no df_master, posso começar a mexer nos dados.

2.1 Descrições de espécies ao longo do tempo


Das 38079 espécies presentes no df_master, 23.415 possuem a informação referente ao ano de descrição. Isso corresponde a cerca de 61.4905854% da amostra. Ainda assim, um dado interessante de se visualizar:

p1 <- df_master %>% 
  count(desc_year) %>% 
  mutate(desc_century = case_when(desc_year < 1800 ~ "Século 18",
                                      desc_year >= 1800 & desc_year < 1900 ~ "Século 19",
                                      desc_year >= 1900 & desc_year < 2000 ~ "Século 20",
                                      desc_year > 2000 ~ "Século 21")) %>% na.omit() %>% 
  ggplot(aes(x=desc_year,y=n,color=desc_century)) +
  geom_line(aes(group=1)) + coord_cartesian(ylim = c(0,900), xlim = c(1750,2020)) +
  theme_bw() +
  removeGridX() +
  theme(panel.border = element_blank()) + geom_smooth(aes(group=1),alpha=0.1, linetype = 'dashed', size = 0.5, color = 'black') +
geom_text(aes(x = 1920, y = 750, label = "855 espécies \ndescritas em 2001"), 
             hjust = 0, 
             vjust = 0.5, 
             lineheight = 0.8,
             colour = "#555555", 
             label.size = NA, 
             size = 4) +
  geom_curve(aes(x = 2001, y = 855, xend = 1980, yend = 800),
                             colour = "#555555", 
                             size=0.5, 
                             curvature = 0.2,
                             arrow = arrow(length = unit(0.03, "npc"))) +
  scale_color_manual(values = c("#1380A1","#990000", "#FAAB18","#588300")) +
  scale_x_continuous(limits=c(1750,2020), breaks = seq(1750,2020,50)) + xlab('') +
  theme(legend.title = element_blank()) + ggtitle('Número de descrições anuais de espécies no Brasil de 1750 a 2020') +
  ylab("Total de espécies") + xlab("Ano") +
  scale_y_continuous(limits = c(0,800),breaks=seq(0,800,150)) +
  geom_curve(aes(x = 1990, y = 750, xend = 2005, yend = 750), 
                             colour = "#555555", 
                             size=0.5, 
                             curvature = 0.2,
                             arrow = arrow(length = unit(0.03, "npc")))

p1

A curva indica um aumento na taxa de descrições ao longo do século 18, seguida por leve diminuição na taxa em meados do século 19, que finalmente, assume uma taxa de crescimento constante a partir daí, com o ano com maior número de descrições sendo 2001.

Também é interessante ver a diferença das taxas e números absolutos por século:

p2 <- df_master %>% 
  count(desc_year) %>% 
  mutate(desc_century = case_when(desc_year < 1800 ~ "Século 18",
                                      desc_year >= 1800 & desc_year < 1900 ~ "Século 19",
                                      desc_year >= 1900 & desc_year < 2000 ~ "Século 20",
                                      desc_year > 2000 ~ "Século 21")) %>% na.omit() %>% 
  ggplot(aes(x=desc_century,y=n,fill=desc_century)) + geom_boxplot() +
  scale_fill_manual(values = c("#1380A1","#990000", "#FAAB18","#588300")) +
  theme_bw() +
  removeGridX() +
  theme(panel.border = element_blank(), legend.position = "none",
        plot.title = element_text(size=10)) + xlab("") + ylab("") +
  scale_y_continuous(limits = c(0,800),breaks=seq(0,800,150)) + ggtitle("Distribuição do número de descrições anuais,\npor século.")

p3 <- df_master %>% 
  count(desc_year) %>% 
  mutate(desc_century = case_when(desc_year < 1800 ~ "Século 18",
                                  desc_year >= 1800 & desc_year < 1900 ~ "Século 19",
                                  desc_year >= 1900 & desc_year < 2000 ~ "Século 20",
                                  desc_year > 2000 ~ "Século 21")) %>% na.omit() %>% 
  group_by(desc_century) %>% summarise(total=sum(n)) %>% 
  ggplot(aes(x=desc_century,y=total, fill = desc_century)) + geom_bar(stat='identity') +
  scale_fill_manual(values = c("#1380A1","#990000", "#FAAB18","#588300")) +
  theme_bw() +
  removeGridX() +
  theme(panel.border = element_blank(), legend.position = "none",
        plot.title = element_text(size=10)) + xlab("") + ylab("") +
  ggtitle("Total de descrições por século.")





(grid_p <- plot_grid(p2,p3, nrow=1,ncol = 2,labels = c('A', 'B')))

Os boxplots do número de espécies descritas anualmente por século (A) indica um relativo baixo número de descrições no século 18, algo esperado pela recém criação do sistema lineniano. Por outro lado, eles também deixam clara a alta taxa de descrições do século 21, que tem uma mediana de aproximadamente 300 espécies descritas por ano. Os gráficos de barras (B) indicam que, embora apenas 20% do século 21 tenha passado, ele já tem cerca de 80% do total de descrições do século 20.

Usando a coluna desc_author do df_master, é possível ver qual foi o autor mais prolífico de 2001 (ano com maior número de descrições):

head(df_master %>% 
       filter(desc_year == 2001) %>% 
       {table(.$descriptor)} %>% 
       as.data.frame() %>% 
       arrange(desc(Freq))) %>% 
  rename(author=Var1,species_descriptions=Freq)

O fato de o termo Orgs. aparecer no autor com maior número de descrições de 2001, indica se tratar de uma obra. Ainda, o número de espécies descritas associadas com esse nome é muito maior que a média dos demais autores, o que faz sentido, dado que a obra deve compilar descrições de vários autores. Uma busca rápida me mostrou que um livro entitulado “Biodiversidade de algas de ambientes continentais do Estado do Rio de Janeiro”, com as referidas autoras, foi publicado em 2001. Partindo do título, podemos pressupor que uma grande quantidade de algas foram descritas nesse ano. Normalmente espera-se que o número absoluto de angiospermas descritas por ano seja maior que os demais grandes grupos, isso fica evidente quando os dados são agrupados por século e grupo taxonômico:

df_master %>% 
  mutate(desc_century = case_when(desc_year < 1800 ~ "Século 18",
                                      desc_year >= 1800 & desc_year < 1900 ~ "Século 19",
                                      desc_year >= 1900 & desc_year < 2000 ~ "Século 20",
                                      desc_year > 2000 ~ "Século 21")) %>% group_by(desc_century) %>% 
  count(major_group) %>% na.omit() %>% 
 ggplot(aes(x=desc_century,y=n, fill = major_group)) + geom_bar(stat='identity', position = 'dodge') +
ggtitle("Total de espécies descritas (log), por século, agrupado por grupo taxonômico.") +
 scale_fill_manual(values = c("#1380A1",'#177506', "#FAAB18","#f55d42",'#940d8f')) +
  scale_y_log10() + xlab("") + ylab("") + 
  theme_bw() +
  removeGridX() + labs(fill = "Grupo taxonômico") + 
  theme(panel.border = element_blank(),plot.title = element_text(size=10))


A escala do gráfico foi convertida para log, dado que a diferença do número de descrições de gimnospermas (relativamente baixo) acaba mascarando a presença delas. Gimnospermas aparecem descritas apenas no século 19 e 21, sendo a maioria no primeiro. Angiospermas correspondem ao grupo com maior número de descrições em todos séculos, embora a diferença entre estas e as algas seja bem menor no século 21.

Olhando por outra ótica, usando um gráfico de violino, é possível reparar essas particularidades ainda melhor:

df_master %>% ggplot(aes(y=as.numeric(desc_year),x=major_group,fill=major_group)) +
  xlab("Major group") + 
                ylab("Description year") + 
                geom_violin(color = "black") + 
  geom_curve(aes(y = 1980, yend = 1999, x = 1.70, xend=1.5), 
                             colour = "black", 
                             size=0.5, 
                             curvature = 0.2,
                             arrow = arrow(length = unit(0.03, "npc"))) +
                scale_fill_manual(values=c("#1380A1",'#177506', "#FAAB18","#f55d42",'#940d8f')) + 
                theme_bw() + 
                theme(plot.title = element_text(hjust=0.5),
                      legend.position = "none") +
                removeGridX() +
  geom_text(aes(x = 1.7, y = 1963, label = "Pico \nem 2001"),
             colour = "black", 
             label.size = NA, 
             size = 4)+
              ylab("Grupo taxonômico") + xlab("Ano de descrição") +
              theme(panel.border = element_blank()) +
  geom_curve(aes(y = 1800, yend = 1850, x = 4.54, xend=4.1), 
                             colour = "black", 
                             size=0.5, 
                             curvature = 0.2,
                             arrow = arrow(length = unit(0.03, "npc"))) +
                scale_fill_manual(values=c("#1380A1",'#177506', "#FAAB18","#f55d42",'#940d8f')) + 
                theme_bw() + 
                theme(plot.title = element_text(hjust=0.5),
                      legend.position = "none") +
                removeGridX() +
  ggtitle("Distribuição do número de descrições anuais, agrupadas por grupo taxonômico") + 
  geom_text(aes(x = 4.5, y = 1778, label = "Alta densidade\nno século 19"),
             colour = "black", 
             label.size = NA, 
             size = 4)+
              xlab("Grupo taxonômico") + ylab("Ano de descrição") +
              theme(panel.border = element_blank(),plot.title = element_text(size=10)) 


Nele fica clara a maior densidade de descrições de gimnospermas no século 19, característica exclusiva ao grupo. O gráfico também reforça a importância da obra de 2001 no histórico de descrições das algas. Inclusive, embora na maior parte dos anos o grupo com maior número de descrições seja o das angiospermas, em 2001 esse não foi o caso:

df_master %>% filter(desc_year==2001) %>%  
  count(major_group) %>% na.omit() %>% 
 ggplot(aes(x=major_group,y=n, fill = major_group)) + geom_bar(stat='identity', position = 'dodge') +
 scale_fill_manual(values = c("#1380A1",'#177506', "#FAAB18","#f55d42",'#940d8f')) +
  ggtitle("Total de espécies descritas em 2001, por grupo taxonômico.") + xlab("") +
  ylab("") + 
  theme_bw() +
  removeGridX() +
  theme(panel.border = element_blank(), legend.position = "none")

Em 2001 o total de algas descritas foi quase o triplo do de angiospermas. Além dessa questão, dado que a obra trata do estado do Rio de Janeiro, espera-se que isso seja refletido no total de espécies descritas para o estado neste ano. Isso pode ser visualizado em um heatmap, primeiro englobando todo intervalo de tempo de descrições da amostra:

df_master$desc_year <- as.character(df_master$desc_year)
df_temp <- df_stack_parse(df_master,column1 = "desc_year",column2 = "states",slice_value = 3,parse1 = FALSE)

x <- df_temp[[1]] # selecionando o input que preciso da funcao que escrevi
x <- x %>% filter(y != "NA") # remover NA
x$x <- as.numeric(x$x) # converter o ano para numerico
x$y <- as.factor(x$y) 
# pequeno macete para conseguir colocar os estados dos dois lados do plot
x <- x %>% filter(!is.na(y)) 
labs2 <- levels(x$y) 
labs2 <- c("ES", "MG", "RJ","SP", 
                         "PR","RS","SC",
                         "DF","MS","MT","GO",
                         "SE","RN","PI","PE","PB","MA","CE",
                         "BA","AL","TO","RR","RO","PA","AM","AP","AC")

# agora construo o heatmap

x %>% 
  mutate(y = fct_relevel(y, 
                         "ES", "MG", "RJ","SP", 
                         "PR","RS","SC",
                         "DF","MS","MT","GO",
                         "SE","RN","PI","PE","PB","MA","CE",
                         "BA","AL","TO","RR","RO","PA","AM","AP","AC")) %>% 
  ggplot(aes(x, as.numeric(y), fill= value)) + # nomes de estado como numericos
  geom_tile(colour = "black") + 
  scale_fill_gradientn(colours = pal, name = "Total de espécies", na.value = "black") + 
  xlab("Year") + ylab("State") + 
  theme_bw() +
  theme(axis.text.x = element_text(angle = 90),
        plot.title = element_text(hjust=0.5,face="bold"),
        panel.background = element_rect(fill="black", colour="black"),
        panel.grid.major = element_blank(), 
        panel.grid.minor = element_blank()) + 
  scale_x_continuous(breaks = seq(1750,2020,10), 
                     expand = c(0,0)) + # tirando o panning
  scale_y_continuous(breaks = 1:length(labs2), 
                     labels = labs2, # mascarando os fatores com nomes 
                     sec.axis = sec_axis(~., # eixo secundario para ter estados dos dois lados
                                         breaks = 1:length(labs2),
                                         labels = labs2),expand = c(0,0)) +
  xlab("Ano") + ylab("Estado") + ggtitle("Descrição de espécies/ano/estado no Brasil de 1750 a 2020.")

Este gráfico representa o número de espécies descritas por ano, por estado da federação. Os estados foram propositadamente ordenados por região, para expor o fato de que os estados do sudeste são, em geral, mais bem amostrados que os demais, especialmente quando se trata de anos recentes. Este já é um fato conhecido, por estas regiões receberem mais recursos para a pesquisa. Ainda assim vale observar a quantidade expressiva de espécies descritas para os estados da Bahia, Pará e Amazonas. A mancha vermelha no gráfico representa o estado do Rio de Janeiro, no ano de 2001. Restringindo o gráfico para décadas mais recentes este fato fica mais claro:

x %>% 
  mutate(y = fct_relevel(y, 
                         "ES", "MG", "RJ","SP", 
                         "PR","RS","SC",
                         "DF","MS","MT","GO",
                         "SE","RN","PI","PE","PB","MA","CE",
                         "BA","AL","TO","RR","RO","PA","AM","AP","AC")) %>% 
  ggplot(aes(x, as.numeric(y), fill= value)) + 
  geom_tile(colour = "black") + 
  scale_fill_gradientn(colours = pal, 
                       name = "Total de espécies",
                       na.value = "black") + 
  xlab("Year") + ylab("State") + 
  theme_bw() +
   geom_vline(xintercept=2000, linetype = "dashed",size = 0.5) +
   geom_vline(xintercept=2010, linetype = "dashed",size = 0.5) +
  theme(axis.text.x = element_text(angle = 90),
        plot.title = element_text(hjust=0.5,face="bold")) + 
  coord_cartesian(xlim = c(1990,2019)) + # limitando anos que aparecem no plot
  scale_x_continuous(breaks = seq(1990,2019,1), expand = c(0,0)) + 
  scale_y_continuous(breaks = 1:length(labs2), 
                     labels = labs2,
                     sec.axis = sec_axis(~., 
                                         breaks = 1:length(labs2),
                                         labels = labs2),expand = c(0,0)) +
  xlab("Ano") + ylab("Estado") + ggtitle("Descrição de espécies/ano/estado no Brasil de 1990 a 2020.")

Além dos fatos já expostos e reforçados, é possível ver que a década entre 2000 e 2010 foi a mais prolífica até então na quantidade de espécies nativas descritas. Ainda, esse número parece cair expressivamente a partir de 2013.

Poderíamos esperar que, além da questão do financiamento, estados maiores possuem maior quantidade de espécies descritas, mas este definitivamente não é o caso, uma vez que o Rio de Janeiro, por exemplo, é um dos menores estados brasileiros.

Agregando mais algumas informações isso também pode ser melhor visualizado. Além do número de espécies descritas por ano, vou combinar a extensão territorial dos estados, se eles fazem fronteiras internacionais ou não e a proporção de espécies endêmicas do total de espécies nativas descritas em cada um. Plotando todos esses dados em um único gráfico, posso tentar visualizar algumas coisas:

  1. O tamanho dos estados está correlacionado com o total de espécies descritas?
  2. Estados com fronteiras internacionais tem menor proporção de espécies endêmicas?
  3. Quais estados tem maior número de espécies descritas e proporção de endêmicas?
# vetor com iniciais de cada estado
states <- c("TO","SE","SP","SC","RR","RO","RS","RN","RJ","PI","PE","PR","PB","PA","MG","MS","MT","MA","GO","ES","DF","CE","BA","AM","AP","AL","AC")

# vetor com presenca/ausencia de fronteiras internacionais
border <- c("Não","Não","Não","Sim","Sim","Sim","Sim","Não","Não","Não","Não", "Sim","Não","Sim","Não","Sim","Sim","Não","Não","Não","Não","Não","Não", "Sim","Sim","Não","Sim")

#area de cada estado em km2
area <- c(277720,21915,248222,95736,224300,237590,281730,52811,43780,251577,98311,199307,56585,1247954,586522,357145,903366,331937,340111,46095,5779,148920,564733,1559159,142828,27778,164123)

# combinando tudo em um df
df_states <- tibble(state=states,area=area,border=border) 

# endemicas e nao endemicas por estado
  # coluna de endemismo NAO precisa de parsing
df_state_endemism <- df_stack_parse(df_master,
                                    column1 = "endemism",
                                    column2 = "states",
                                    parse1 = FALSE)[[1]] 

# total de especies por estado
a <- df_state_endemism %>% 
      group_by(y) %>% 
      summarise(species=sum(value))

# total de endemicas por estado
b <- df_state_endemism %>% filter(x=="Endemica") %>% group_by(y) %>% summarise(endemics=sum(value))

# junto os dois e calculo as props

c <- left_join(a,b,by = "y") %>% 
      mutate(prop= endemics*100/species) %>% 
      rename(state=y) 

k <- left_join(c,df_states,by="state")

# pequena abordagem para marcar o que quero no plot
k[['temp']] <- ""
labels <- c(13,3,11,15,5,20,27,8,9,14,19,26)
k[['temp']][labels] <- k$state[labels]

# primeiro o scatter

p1 <- k %>% filter(state != "NA") %>% ggplot(aes(x=species,y=prop,size=area,label=state,color=border)) + 
  geom_point() + 
  geom_smooth(aes(group=1),alpha=0.1, linetype = 'dashed', size = 0.5, color = 'black',method="lm") +
  scale_color_manual(values=c(pal[1],pal[5]), name = "miau") + 
  geom_hline(yintercept=20, linetype = "dashed",size = 0.1) +
  geom_hline(yintercept=40, linetype = "dashed",size = 0.1) +
  ylab("Proporção de endêmcias (%)") + xlab("Total de espécies") +
  theme_bw() +
  geom_label_repel(aes(label = temp),
                   box.padding   = 0.35, 
                   point.padding = 0.5,
                   segment.color = 'grey50') +
  scale_size(guide = "none") +
  theme(legend.position = "none",panel.border = element_blank()) 
  
  
# agora o boxplot

p2 <- k %>% na.omit() %>% ggplot(aes(y=prop,fill=border,x=border)) + 
  geom_boxplot() +
  theme_bw() + 
  scale_fill_manual(values = c(pal[1],pal[5])) +
  ylab("Proporção de endêmicas (%)") +
  xlab("") + 
  theme(axis.text.x = element_blank(),legend.position = "left",panel.border = element_blank()) +
  labs(fill = " Limites \n internacionais")

# combinando tudo em um grid

p3 <- plot_grid(p1,p2, ncol = 2, labels = c("A","B"))

# adicionando um titulo

title <- ggdraw() +
  draw_label(
    "Relação entre as proporções de espécies endêmicas, total de espécies \ne seus estados de ocorrência (A). Proporção de espécies endêmicas em \nestados com e sem fronteira (B).",
    fontface = 'bold',
    size=10,
    x = 0,
    hjust = 0
  ) +
  theme(
    plot.margin = margin(0, 0, 0, 7)
  )
plot_grid(
  title, p3,
  ncol = 1,
  rel_heights = c(0.1, 1)
)

Esses gráficos contém uma grande quantidade de informação. Primeiramente, o tamanho dos estados não parece influenciar na quantidade de espécies descritas. Os maiores estados brasileiros (Amazonas, Pará e Mato grosso, marcados no gráfico), contém uma quantidade de espécies descritas menor do que estados como o Rio de Janeiro, São Paulo ou Bahia. Estes, por sua vez, juntamente com o Minas Gerais, também possuem as maiores proporções de espécies endêmicas do total de suas espécies nativas. Como o esperado, estados fronteiriços possuem proporção menor de endêmicas: todos aqueles mais de 40% de sua flora sendo endêmica não fazem fronteiras internacionais. A lógica contrária também se aplica, dado que todos estados com menos de 20% de sua flora sendo endêmcia possuem fronteiras internacionais.

Vale notar, ainda, que os quatro estados com maiores valores de riqueza de espécies e proporção de endêmicas abrigam principalmente os domínios da Mata Atlântica e do Cerrado, dois conhecidos hotspots da biodiversidade, com altas taxas de diversidade em senso amplo. Estes domínios, juntamente com a Caatinga, possuem as maiores proporções de endemismo do país:

df_temp <- df_stack_parse(df_master,column1 = "endemism",
                          column2 = "phytogeographic_domains",
                          parse1 = FALSE, slice_value = 3)
  df_temp[[1]] %>% 
    mutate(y = fct_relevel(y, 
                          "Mata Atlântica", "Cerrado", "Caatinga", 
                          "Amazônia", "Pampa", "Pantanal")) %>%
  ggplot(aes(fill=x, y=value, x=y)) + 
    ylab("Proportion") +
    xlab("Phytogeographic domain") +
  geom_bar(position="fill", stat="identity", color = "black") +
  theme_bw()  + xlab("") + ylab("") +
  scale_fill_manual(name = "Endemismo",values=c(pal[5],pal[1]), aesthetics = "fill",labels=c("Endêmicas","Não endêmicas")) +
  removeGridX() +
  theme(panel.border = element_blank()) + ggtitle("Proporção de espécies endêmicas por domínio fitogeográfico.")

2.2 Incluindo variáveis ecológicas


Mudando drasticamente a análise de direção, ainda existem mais algumas variáveis a serem checadas. Vou explorar um pouco agora os dados de formas de vida e tipos de vegetação de ocorrência das espécies. Primeiro uma olhada nas formas de vida mais frequentes da flora brasileira:

df_life_forms <- as_tibble(as.data.frame(table(unlist(strsplit(as.character(df_master$life_form),split=";")))))
p1 <- df_life_forms %>% 
  mutate(Var1=fct_reorder(Var1,desc(Freq))) %>% 
  ggplot(aes(fill=Var1,y=Freq,x=Var1)) + 
         geom_col(position = "dodge",fill=pal[1], color = "black") + 
         xlab("") +
         ylab("") +
         theme_bw() +
         theme(axis.text.x = element_text(angle = 90,size = 10),panel.border = element_blank(),
               plot.title = element_text(size=10)) +
  removeGridX() + ggtitle("Total de espécies em cada forma de vida")

p2 <- df_master %>%
  count(major_group) %>% na.omit() %>% mutate(major_group=as.factor(major_group)) %>% 
  mutate(major_group=fct_reorder(major_group,desc(n))) %>% 
 ggplot(aes(x=major_group,y=n, fill = major_group)) + geom_bar(stat='identity', position = 'dodge') +
 scale_fill_manual(values = c('#177506', "#1380A1", "#FAAB18", '#940d8f', "#f55d42")) +
  theme_bw() +
  xlab("") +
  ylab("") +
  theme(axis.text.x = element_text(angle = 90,size = 10),
        legend.position = "none",plot.title = element_text(size=10)) +
  removeGridX() +
  theme(panel.border = element_blank(),
        legend.position = "none") +
  ggtitle("Total de espécies em cada grupo taxonômico")

(p3 <- plot_grid(p1,p2, ncol = 2))

Não inesperadamente, as formas de vida mais frequentes são aquelas associadas com angiospermas, seguidas de formas de vida associadas à algas e depois briófitas. Após as dez formas de vida mais frequentes (que seguem a ordem descrescente supracitada), vemos formas de vida variadas, sem ordem taxonomica. Vale ressaltar que algumas das formas de vida associadas à angiospermas são compartilhadas por samambaias, licófitas e gimnospermas, o que influencia nesse resultado, ainda que sejam grupos com quantidade menor de espécies descritas (gimnospermas parecem sequer existir no gráfico, devido ao fato do número ser muito pequeno).

Formas de vida são frequentemente associadas com os ambientes em que as espécies ocorrem. Não seria, a princípio, esperado que formas de vida ligadas a briófitas ocorressem em alta frequência em uma vegetação de clima quente e seco. Como ambos esses dados estão disponíveis, visualizando-os em conjunto podem potencialmente revelar alguns padrões interessantes. Para isso vou plotar os tipos de vegetação mais frequentemete associados a cada forma de vida, no formato de um gráfico de barras empilhado:

# limpando os simbolos
df_master$vegetation_type <- gsub("\\(","",df_master$vegetation_type)  
df_master$vegetation_type <- gsub("\\)","",df_master$vegetation_type)
df_master$vegetation_type <- gsub("=","",df_master$vegetation_type)
df_master$life_form <- as.character(df_master$life_form)

# aplicando a funcao
    # setando o slice para 3

df_temp <- df_stack_parse(df_master,column1 = "life_form",column2 = "vegetation_type",slice_value = 3)

  df_temp[[2]] %>% # selecionando o df com os top 3 de cada caso
  ggplot(aes(fill=y, y=value, x=x)) + 
  ylab("") + 
  xlab("") +
  geom_bar(position="fill", stat="identity", color = "black") + 
    scale_fill_brewer(palette = "Paired") + 
    theme_bw() + 
    labs(fill='Tipo de vegetação') +
    theme(axis.text.x = element_text(angle = 90,size = 20),
          axis.text.y = element_text(size = 20),
          axis.title = element_text(size = 20),
          legend.text=element_text(size=20),
          legend.title = element_text(size=20),
          plot.title = element_text(size=20),
          panel.border = element_blank()) +
  removeGridX() + ggtitle("Três  tipos de vegetação mais frequentes, agrupados por forma de vida.")

Nesse gráfico estão representadas os três tipos de vegetação mais frequentes para cada forma de vida de maneira proporcional. Não existem tipos de vegetação associados à algas, por isso a ausência dessa informação no gráfico. Fica logo evidente a frequência em que domina a floresta ombrófila (laranja), dentre as demais formas de vida. Quase todas formas de vida tem essa vegetação dominando dentre as mais frequentes, o que é minimamente esperado dado que uma grande quantidade de espécies nativas ocorre em Mata Atlântica, domínio à qual este tipo de vegetação está mais associado. Outro fato interessante evidenciado por esse gráfico é a importância das vegetações sobre afloramentos rochosos (roxo) para espécies suculentas: apenas nestas, este tipo de vegetação figura entre os mais frequentes. É também curioso que a Floresta Ombrófila Mista (lilás) esteja aparecendo nesse gráfico, dado que trata-se de um tipo de vegetação bastante devastado e restrito a regiões específicas do sul do Brasil. Ainda, todas as formas de vida que possuem essa vegetação figurando como frequente estão associadas a briófitas, algo que merece uma investigação futura.

2.3 Nomes vernaculares


Por último, vou analisar rapidamente alguns dados a respeito dos nomes populares disponíveis para as espécies. Quero responder duas perguntas simples:

  1. Dentre as espécies com essa informação disponível, qual o nome popular mais frequente na amostra?
  2. Nomes populares podem se referir a espécies de famílias botânicas diferentes?

Esses dados tem que ser limpos novamente para que a análise fique menos enviesada, dado que estes são um pouco mais sensíveis de se trabalhar. Alguns nomes aparecem capitalizados, outros não, além disso alguns símbolos não alfanuméricos podem atrapalhar a contagem. Esse é um assunto por si só, mas farei uma pequena limpeza aqui nos nomes para melhorar o resultado e fragmentar os nomes (lembrando que cada nome vernacular de determinada espécie é separado por “;”, como no casos dos estados da federação):

# removendo os hifens
df_master$vernacular_name <- tolower(gsub("-"," ",df_master$vernacular_name))

# substituindo as virgulas por pontos e virgulas
  # isso deixa todos separadores iguais
  # alguns nomes estavam separados por virgulas

df_master$vernacular_name <- tolower(gsub(",",";",df_master$vernacular_name))

# lista dos nomes mais frequentes 

{table(na.omit(unlist(strsplit(df_master$vernacular_name,split=";"))))} %>% # vetor com todos nomes populares da amostra
{as_tibble(as.data.frame(.))} %>% arrange(desc(Freq)) %>% # contagem de frequencias, output como data frame
head() # seis nomes mais frequentes

O nome popular “Taquara” é o mais frequente nessa amostra, relacionado comumente com uma variedade de bambus (família Poaceae), conhecidas por terem uso amplo, desde para a construção em geral como para a criação de instrumentos musicais. Nesse caso, todas espécies associadas com esse nome parecem pertencer à mesma família:

as.character(unique(df_master$family[grep("taquara",df_master$vernacular_name,ignore.case = T)]))
## [1] "Poaceae"

O segundo colocado em nossa lista já não segue esse padrão:

table(as.character(df_master$family[grep("envira",df_master$vernacular_name,ignore.case = T)]))
## 
##    Annonaceae      Fabaceae Lecythidaceae     Malvaceae    Salicaceae 
##            80             1             1             3             1 
## Thymelaeaceae      Ulmaceae 
##             1             2

Embora a esmagadora maioria das espécies com o nome “Envira” associado pertençam à familia Annonaceae, ele também aparece associado a espécies de outras famílias. Embora não seja um resultado surpreendente, continua sendo um fato interessante.