knitr::opts_chunk$set(echo = TRUE)
Esse tutorial foi pensado para auxiliar curadores de herbário que pretendem atualizar suas coleções usando informações oriundas de duplicatas depositadas em outras coleções. Como realizar esse processo para a coleção inteira demandaria obter as bases de dados de todas as coleções biológicas, os códigos abaixo foram preparados para serem executados por famílias individualmente.
Agradecimentos especiais ao André L. de Gasper pelos testes do pacote e pela sugestão de criar esse tutorial mais dirigido aos curadores de herbário.
Antes de começar precisamos carregar o pacote usando a função library()
,
assumindo que você tem o pacote instalado junto ao seu R
. Se você ainda não
tem o pacote instalado em seu computador, siga as instruções do tutorial geral
do pacote (i.e., 'plantr_tutorial.html').
library("plantR")
Iremos usar a família Blechnaceae para esse exemplo, e baixando dados tanto do
speciesLink (INCT) quanto do GBIF. O GBIF possui mais de 430,000 registros para
a família no mundo todo. Assumindo que o curador seja de uma coleção do Brasil,
iremos baixar apenas as coletas realizadas no Brasil (i.e., campo country
igual a 'BR').
Para downloads do GBIF, o limite do número de registros baixados é controlado
pelo argumento n.records
e o padrão é baixar até 5000 registros por item
buscado. Então o limite foi modificado para baixar mais registros. Contudo, há
um limite do número máximo de 100,000 registros que podem ser baixados de um só
vez. Por isso, iremos baixar apenas os registros da família para o Brasil
(<100,000). Veja o help da função rgbif2()
para sugestões sobre como fazer
para famílias com mais de 100,000 registros no GBIF.
Note que o campo species
da função rgbif2()
aceita não apenas nomes ao nível
de espécie, mas em qualquer nível taxonômico. Para a função rspeciesLink()
,
há um campo específico para o nome da família (i.e., family
).
familia <- "Blechnaceae" occs_splink <- rspeciesLink(family = familia) occs_gbif <- rgbif2(species = familia, country = "BR", n.records = 450000) dim(occs_splink) dim(occs_gbif)
Foram encontrados aproximadamente 24,000 registros para a família no speciesLink e aprox. 23,000 registros para o Brasil no GBIF.
Em seguida, combinamos os registros dos dois repositórios em apenas um objeto
usando a função formatDwc()
e removendo colunas desnecessárias para a busca de
duplicatas:
occs <- formatDwc(splink_data = occs_splink, gbif_data = occs_gbif, drop = TRUE) dim(occs)
Veja que o objeto occs
contém agora a soma dos registros vindos do speciesLink
e GBIF (i.e., aprox. 47,000 em Abril de 2021).
Mesmo que você esteja interessado apenas em atualizar um tipo de informação (e.g., nome da espécie), é importante padronizar a notação e formato de campos que são importantes para a busca de duplicatas. Essa padronização não é perfeita, mas ela aumenta as chances de recuperar duplicatas com pequenas diferenças de notação em campos como nome e número do coletor, a localidade da coleta, nome da família e a grafia e/ou formato do nome da espécie.
O pacote plantR possui funções que executam várias dessas edições de uma só
vez. As funções formatOcc()
, formatLoc()
, formatCoord()
e formatTax()
fazem a padronização dos campos relacionados à coleta em si (e.g., código da
coleção, nome e número do coletor), à localidade da coleta, às coordenadas
geográficas associadas à coleta e à informação taxonômica.
A verificação ortográfica e de sinônimos via o The Plant List é relativamente
demorada. Portanto, iremos fazer a conferência e validação dos nomes apenas
usando a Flora do Brasil (i.e., campo db
igual a 'fbo')
occs <- formatOcc(occs) occs <- formatLoc(occs) occs <- formatCoord(occs) occs <- formatTax(occs, db = "fbo")
Note que as funções não editam as colunas originais dos registros. Elas criam novas colunas que armazenam as informações editadas que em geral têm o mesmo nome da coluna original seguido do sufixo '.new'.
Para cada conjunto de duplicatas, a tomada de decisão de qual espécimen será usado para obter a informação válida ou a mais atual sobre localidade, coordenadas geográficas ou identificação taxonômica depende de um processo de validação. Esse processo de validação não é essencial para encontrar as duplicatas entre coleções, mas ela ajuda no processo de tomada de decisão sobre qual é a melhor informação disponível.
Assim como para a padronização dos campos, o pacote plantR oferece funções
que executam essas validações de uma só vez. As funções validateLoc()
e
validateCoord()
fazem a validação dos campos de localidade e coordenadas
geográficas, respectivamente.
occs <- validateLoc(occs) occs <- validateCoord(occs)
A função validateTax()
faz uma classificação da confiabilidade da
identificação taxonômica dos registros. Essa avaliação é feita em uma base
global de nomes de taxonomistas por família (veja o help da função
digitando ?validateTax no seu console do R).
Contudo, essa base de dados não é completa. Assim, pode ser importante executar a função de maneira preliminar para avaliar se não há nomes de taxonomistas que sejam relevantes à essa avaliação e que não estejam na base de dados. Vamos portanto visualizar os 15 nomes com mais determinações para a família usado no exemplo, e que não estão listados na base de dados como especialistas da família:
temp <- validateTax(occs, top.det = 15) rm(temp)
Note que entre os nomes listados há vários especialistas do grupo, mas que não são exatamente especialistas da família em questão (e.g., 'Gonzatti, F.'). Outros nomes podem estar listados porque a base de dados usada está incompleta.
Para incluir nomes faltantes de taxonomistas, é possível usar o campo
miss.taxonomist
. Nesse exemplo vamos incluir dois nomes 'Kazmirczak, C.' e
'Prado, J.', que têm que ser fornecidos em um formato específico: nome da
'família + underline + nome do determinador.
falta.tax <- paste(familia, c("Kazmirczak, C.", "Prado, J."), sep = "_") occs <- validateTax(occs, miss.taxonomist = falta.tax, top.det = 15)
Note que agora os nomes incluídos já não são mais listados entre os nomes com mais identificações, mas que não são especialistas da família.
Para a busca de duplicatas, precisamos de algumas informações adicionais. Uma
delas é ter um identificador único para cada registro (i.e., número de tombo).
Para isso podemos concatenar o código padronizado da coleção e seu número de
registro ou tombo na coleção correspondente. Isso pode ser feito usando a função
getTombo()
:
occs$numTombo <- getTombo(occs[, "collectionCode.new"], occs[, "catalogNumber"])
Como muitas coleções têm suas bases de dados tanto no speciesLink/INCT quanto no GBIF é normal termos números de tombo repetidos nos dados, as chamadas duplicatas virtuais. Como nosso interesse é pelas informações contidas nas duplicatas físicas entre coleções, é indicado remover números de tombo repetidos. Isso não afeta a busca por duplicatas, mas simplifica a sua checagem final, isto é, as duplicatas virtuais não estarão entre as duplicatas encontradas.
Como alguns registros não têm número de tombo (tombo igual a 'US_NA'), usamos o código abaixo para realizar a remoção apenas dos números de tombo repetidos:
dim(occs)[1] occs <- occs[!duplicated(occs$numTombo) | grepl("_NA$", occs$numTombo, perl = TRUE),] dim(occs)[1]
Note que cerca de um terço dos registros representavam duplicatas virtuais.
Note também que existe a possibilidade de coleções terem um mesmo número de tombo para registros diferentes, devido a algum tipo um erro. Mas após o código acima, não estamos mais considerando esse tipo de erro.
Uma informação essencial para a busca de duplicatas é a definição de quais campos serão usados na busca por duplicatas. No plantR é possível usar qualquer combinação dos campos contendo a informação do nome da família ou espécie, nome ou sobrenome do coletor, número do coletor, ano de coleta e localidade da coleta.
Como há muita variação de notação entre coleções no nome do coletor, é possível
usar apenas o seu sobrenome. Além disso, como o uso apenas do sobrenome e número
de coletor pode retornar falsas duplicatas para nomes muito comuns e números de
coletor baixos (e.g., Lima 10), é aconselhado incluir outros campos na busca.
Neste exemplo iremos usar três combinações de campos, que são geradas usando a
função prepDup()
:
dups <- prepDup(occs, comb.fields = list(c("species","col.name","col.number"), c("col.last.name","col.number","col.loc"), c("col.last.name","col.number","col.year")))
Note que salvamos os strings concatenados de busca em uma tabela à parte, pois essa informação não será necessária após a busca, evitando aumentar ainda mais o número de novas colunas.
Note também que o padrão da função é não incluir na busca por duplicatas
registros com informação faltante de coletor, data ou localidade, etc. Se você
quiser incluir esses registros o campo ignore.miss
deverá ser modificado de
TRUE
para FALSE
. Mas tome cuidado pois isso pode resultar em muitas falsas
duplicatas!!
Finalmente, podemos usar a nova tabela gerada para buscar os registros com alguma indicação de serem um mesmo espécimen com material depositado em diferentes coleções.
dups <- getDup(dups) head(dups[order(dups$dup.ID),], 4)
Novas colunas foram criadas. A coluna 'dup.prop' contém a força de indicação das duplicatas (i.e., quanto mais próximo de 1 mais segurança na indicação). Vamos inspecionar as categorias geradas:
table(dups$dup.prop)
Em seguida, precisamos reunir as colunas de interesse da busca de duplicatas com a nossa planilha geral:
occs <- cbind.data.frame(occs, dups[,c("dup.ID", "dup.numb", "dup.prop")], stringsAsFactors = FALSE)
Para esses dados, cerca de 32% dos registros possuem forte indicação de duplicatas e cerca de 37% não tiveram nenhuma indicação (i.e., prováveis unicatas). Além desses, 16% foram classificados com 'dup.prop' igual a 0.667 (e.g., 2 sobre 3 combinações iguais) e 16% como 'cc' de 'cannot check' por falta de informações associadas aos campos escolhidos. Para registros com 'dup.prop' <0.5 (apenas 1 combinação em comum) sugere-se um 'pente-fino', pois esses casos podem representar problemas ou falsas duplicatas.
Por fim, podemos usar para todas as duplicatas de cada grupo as informações mais
confiáveis ou recentes sobre os registros. Atualmente, o plantR faz essa
homogeneização para as informações de localidade, coordenadas geográficas e/ou
taxonomia. Ela é feita usando a função mergeDup()
cujo padrão é fazer apenas o
merge para registros com 'dup.prop' > 0.75. Isso pode ser alterado usando o
campo prop
da função, como abaixo.
occs <- mergeDup(occs, prop = 0.65)
O default dessa função usa os campos já editados pelo plantR e cria novas colunas com um '1' adicionado ao final do nome da coluna (e.g., coluna 'family.new' após a homogeneização será armazenada na nova coluna 'family.new1'). Lembre-se, contudo, que os nomes das colunas que serão usadas podem ser definidas pelo usuário (e.g., usar a coluna 'family' ao invés da 'family.new').
Podemos comparar as mudanças obtidas para um dos campos, como por exemplo, o campo que define o nível de confiança na identificação do registro. Note que 300 e 700 registros que possuíam nível definido como 'unknown' e 'low' passaram a ter um nível definido como 'high'.
table(occs$tax.check, occs$tax.check1, dnn = c("antes", "depois"))
Para esse tutorial, vamos supor que o André L. de Gasper, atual curador do herbário FURB, queira comparar os materiais depositados no FURB com as demais coleções. Mais especificamente, ele quer atualizar as informações relacionadas à identificação taxonômica e aos campos de determinação.
Primeiro, precisamos definir o nome da coleção focal e filtrar quais registros possuem direta ou indiretamente informações que podem ser relevantes. No caso, iremos definir o FURB como a coleção focal.
colecao <- "FURB" occs1 <- occs[grepl(colecao, occs$numTombo, perl = TRUE) | grepl(colecao, occs$dup.ID, perl = TRUE), ] dim(occs1)
Podemos inspecionar quantos registros há por coleção:
table(occs1$collectionCode.new)
Note que há cerca de 1700 registros de Blechnaceae no nosso filtro, dos quais aprox. 1300 são de registros do FURB mesmo, e o restante dos registros estão espalhados em cerca de 40 outras coleções.
Se você quiser fazer o mesmo, mas para outra coleção basta trocar o nome da
coleção que é atribuída ao objeto chamado colecao
.
Podemos filtrar apenas as colunas que são de interesse para a checagem alvo que o André quer realizar, a checagem taxonômica. Para cada um dos campos de interesse iremos filtrar as informações básicas de cada registro, mais a informação original (em formato DwC), a editada pelo plantR (sufixo '.new') e a homogeneizada a partir dos grupos de duplicatas (sufixo '.new1') relativas à identificação taxonômica dos registros.
Note que como usamos os defaults do plantR os filtros das colunas também seguem esse padrão. Caso você tenha selecionado outras colunas, os nomes abaixo têm que ser adaptados.
colunas <- c("numTombo", "recordedBy.new", "recordNumber.new", "identifiedBy", "identifiedBy.new", "identifiedBy.new1", "yearIdentified", "yearIdentified.new", "yearIdentified.new1", "family", "family.new", "family.new1", "scientificName", "scientificName.new", "scientificName.new1", "scientificNameStatus", "tax.notes", "tax.check","tax.check1","dup.ID") occs1.tax <- occs1[ , colunas]
table(occs1[grepl("FURB_", occs1$numTombo, fixed = TRUE) & !occs1$tax.notes %in% "", c("scientificName","tax.notes")])
Sem grandes problemas para o FURB! Algumas notas em relação à diferença como os híbridos são anotados na Flora do Brasil e duas espécies que não ocorrem no Brasil.
Para realizar essa operação, podemos realizar uma filtragem mais, para ficarmos apenas com os registros com indicações de duplicata (i.e., coluna 'dup.ID' não vazia):
occs2.tax <- occs1.tax[!is.na(occs1.tax$dup.ID), ] occs2.tax <- occs2.tax[order(occs2.tax$dup.ID), ]
Para facilitar o trabalho do curador, podemos marcar as duplicatas com indicação de alteração da identificação:
occs2.tax$checar.taxon <- !is.na(occs2.tax$scientificName.new) & occs2.tax$scientificName.new != occs2.tax$scientificName.new1 & grepl("FURB_", occs2.tax$numTombo, fixed = TRUE) occs2.tax[occs2.tax$checar.taxon,]
Note que há cinco registros cujo nome encontrado do FURB é diferente do nome encontrado nas demais coleções. Vamos imprimir um exemplo para entender o que as funções estão fazendo. Iremos usar como exemplo o identificador de duplicatas ('dup.ID') 'FUEL_53109|FURB_39824|FURB_6463|HUCS_39468|SLUI_4389| VIC_37877|VIES_27594'.
occs2.tax[grepl('FURB_6463', occs2.tax$dup.ID),]
Para esse caso há identificações feitas por diferentes pessoas e em diferentes
datas. Como descrito no tutorial do plantR, o registro com identificação mais
recente feita por um especialista da família é usado como a identificação de
referência - nesse caso, a identificação feita por 'Dittrich, V.A.O.' em 2018.
O registro 'FURB_6463', assim como o 'SLUI_4389' e o 'VIC_37877', possuem
identificações diferentes e estes tiveram suas informações homogeneizadas
automaticamente pelo plantR (colunas terminando em '.new1') e podem ser
usadas pelo curador do FURB para atualização.
Em seguida, podemos salvar os resultados em uma planilha à parte para
conferência, usando a função saveData()
:
nome.arquivo <- paste(colecao, familia, "taxonomia", sep = "_") saveData(occs2.tax, file.name = nome.arquivo, dir.name = "checagem_plantR", file.format = "csv", compress = FALSE)
Esses registros estão marcados como 'TRUE' na coluna 'checar.taxon' que foi salva na pasta 'checagem_plantR' do seu diretório local. Por fins de organização, usamos a combinação do nome da família e da coleção no nome do arquivo '.csv' salvo localmente.
[EM BREVE]
[EM BREVE]
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.