Introdução

Este documento detalha o algoritmo em R desenvolvido para processar planilhas de ocorrência de espécies por quadrículas (geradas via QGIS) e transformá-las em matrizes binárias. O formato de saída é o padrão NEXUS (.nex), estruturado com blocos rígidos para evitar erros de leitura e estouro de memória no software WinClada/ASADO.

Para utilizar este script, a planilha de entrada deve ter as colunas escritas exatamente como “Species” para as espécies e “id” para as quadrículas.

Antes de rodar este script, role até abaixo no PASSO 2 e coloque os nomes de entrada e saída dos arquivos.


O Passo a Passo do Algoritmo

O script foi estruturado em uma única função chamada gerar_matriz_nexus, que executa as seguintes etapas sequenciais:

  1. Leitura Flexível: Identifica se o arquivo de entrada é .xlsx ou .csv e faz a leitura adequada, lidando com diferentes separadores.
  2. Filtragem e Limpeza: Isola as colunas id (quadrículas) e Species. Remove ocorrências duplicadas da mesma espécie na mesma área (unique()) e higieniza os textos (removendo acentos, espaços e caracteres especiais) para não travar o WinClada.
  3. Matriz Binária e Outgroup: Converte as ocorrências em uma tabela de contingência de presença/ausência (1 e 0). Em seguida, injeta automaticamente uma linha extra preenchida com zeros (Raiz_Outgroup) para permitir o enraizamento da árvore na PAE.
  4. Formatação NEXUS: Concatena os dados alinhando os blocos obrigatórios TAXA (linhas) e CHARACTERS (colunas) da linguagem NEXUS.
  5. Dupla Exportação: Salva o arquivo .nex blindado para o WinClada e, simultaneamente, exporta uma legenda em .xlsx relacionando a numeração final às espécies originais.

Código da Função Completa

PASSO 1

Instale e carregue os pacotes necessários.

# =========================================================================
# VERIFICAÇÃO E INSTALAÇÃO DE PACOTES
# =========================================================================

# Lista dos pacotes necessários para rodar o script
pacotes_necessarios <- c("readxl", "writexl")

# Verifica quais pacotes já estão instalados no computador
pacotes_ausentes <- pacotes_necessarios[!(pacotes_necessarios %in% installed.packages()[,"Package"])]

# Instala os pacotes que estiverem faltando
if(length(pacotes_ausentes) > 0) {
  install.packages(pacotes_ausentes, dependencies = TRUE)
}

# Carrega os pacotes na memória
invisible(lapply(pacotes_necessarios, library, character.only = TRUE))

cat("Pacotes carregados com sucesso!\n")
## Pacotes carregados com sucesso!

Execute o bloco abaixo para carregar a função na memória do R. Como a função está contida inteiramente neste único chunk, o código será processado sem erros de sintaxe.

gerar_matriz_nexus <- function(caminho_arquivo, 
                               arquivo_saida = "Matriz_PAE_Final.nex", 
                               col_id = "id", 
                               col_species = "Species") {
  
  # 1. LEITURA DA ENTRADA (.CSV OU .XLSX)
  extensao <- tolower(tools::file_ext(caminho_arquivo))
  
  if (extensao %in% c("xlsx", "xls")) {
    if (!requireNamespace("readxl", quietly = TRUE)) install.packages("readxl")
    dados <- as.data.frame(readxl::read_excel(caminho_arquivo))
  } else if (extensao == "csv") {
    dados <- read.csv(caminho_arquivo, stringsAsFactors = FALSE, check.names = FALSE)
    if (ncol(dados) == 1) {
      dados <- read.csv2(caminho_arquivo, stringsAsFactors = FALSE, check.names = FALSE)
    }
  } else stop("Formato de entrada não suportado. Utilize arquivos .xlsx, .xls ou .csv.")
  
  # 2. LOCALIZAR AS COLUNAS E FILTRAR
  idx_id <- grep(paste0("^", col_id, "$"), colnames(dados), ignore.case = TRUE)
  idx_sp <- grep(paste0("^", col_species, "$"), colnames(dados), ignore.case = TRUE)
  
  if (length(idx_id) == 0 || length(idx_sp) == 0) {
    stop("Colunas 'id' e/ou 'Species' não encontradas na sua planilha de entrada.")
  }
  
  df_sub <- na.omit(dados[, c(idx_id, idx_sp)])
  colnames(df_sub) <- c("id", "Species")
  df_unicos <- unique(df_sub)
  
  # 3. LIMPEZA RIGOROSA PARA O WINCLADA
  df_unicos$Species <- iconv(df_unicos$Species, to = "ASCII//TRANSLIT")
  df_unicos$Species <- gsub("[^A-Za-z0-9]", "_", trimws(df_unicos$Species))
  df_unicos$id <- iconv(as.character(df_unicos$id), to = "ASCII//TRANSLIT")
  df_unicos$id <- gsub("[^A-Za-z0-9]", "_", trimws(df_unicos$id))
  
  # 4. CONSTRUÇÃO DA MATRIZ BINÁRIA
  mat_tabela <- table(df_unicos$id, df_unicos$Species)
  matriz_binaria <- (mat_tabela > 0) * 1 
  
  # 5. ADICIONAR A RAIZ (OUTGROUP)
  matriz_binaria <- rbind(matriz_binaria, Raiz_Outgroup = 0)
  
  n_taxa <- nrow(matriz_binaria)    
  n_chars <- ncol(matriz_binaria)   
  
  nomes_areas <- rownames(matriz_binaria)
  nomes_areas <- ifelse(nomes_areas == "Raiz_Outgroup", "Raiz_Outgroup", paste0("Q_", nomes_areas))
  nomes_especies <- colnames(matriz_binaria)
  
  # 6. ESTRUTURAÇÃO DOS BLOCOS NEXUS
  bloco_nexus <- c(
    "#NEXUS",
    "",
    "BEGIN TAXA;",
    paste0("  DIMENSIONS NTAX=", n_taxa, ";"),
    "  TAXLABELS",
    paste0("    ", nomes_areas),
    "  ;",
    "END;",
    "",
    "BEGIN CHARACTERS;",
    paste0("  DIMENSIONS NCHAR=", n_chars, ";"),
    "  FORMAT DATATYPE=STANDARD MISSING=? GAP=- SYMBOLS=\"0 1\";",
    "  CHARSTATELABELS"
  )
  
  char_labels <- paste0("    ", 1:n_chars, " ", nomes_especies, ifelse(1:n_chars == n_chars, ";", ","))
  bloco_nexus <- c(bloco_nexus, char_labels, "  MATRIX")
  
  linhas_binarias <- apply(matriz_binaria, 1, paste, collapse = "")
  espaco_max <- max(nchar(nomes_areas)) + 4
  linhas_formatadas <- sprintf(paste0("    %-", espaco_max, "s %s"), nomes_areas, linhas_binarias)
  
  bloco_nexus <- c(bloco_nexus, linhas_formatadas, "  ;", "END;")
  
  # 7. EXPORTAÇÃO DO ARQUIVO NEXUS
  arquivo_conexao <- file(arquivo_saida, encoding = "UTF-8")
  writeLines(bloco_nexus, arquivo_conexao)
  close(arquivo_conexao)
  
  # 8. EXPORTAÇÃO DA LEGENDA EM XLSX
  legenda <- data.frame(Numero_No_Winclada = 0:(n_chars - 1),
                        Nome_Especie = nomes_especies)
  
  arquivo_legenda <- gsub("\\.nex$", "_Legenda.xlsx", arquivo_saida, ignore.case = TRUE)
  
  if (!requireNamespace("writexl", quietly = TRUE)) install.packages("writexl")
  writexl::write_xlsx(legenda, arquivo_legenda)
  
  cat("\n--- Processamento Concluído ---\n")
  cat("Matriz NEXUS salva em:", file.path(getwd(), arquivo_saida), "\n")
  cat("Legenda XLSX salva em:", file.path(getwd(), arquivo_legenda), "\n\n")
}

PASSO 2

Escolha abaixo o comando dependendo do seu formato de arquivo de entrada. Aqui será gerado o arquivo em formato .nex limpo para rodar no winclad.exe.

# =========================================================================
# ÁREA DE EXECUÇÃO
# =========================================================================

# nas linhas abaixo, retire os "###" para ativar os comandos ou adicione
# os "###" para desativar os comandos, dependendo do formato da planilha

# Exemplo 1: Utilizando uma planilha Excel (.xlsx)
gerar_matriz_nexus(
  caminho_arquivo = "nome_do_arquivo_entrada.xlsx", 
  arquivo_saida = "nome_do_arquivo_saida.nex"         
)

# Exemplo 2: Utilizando um arquivo de texto (.csv)
### Para usar, basta apagar as hashtags abaixo e colocar as da linha do xlsx
### gerar_matriz_nexus(
###   caminho_arquivo = "nome_do_arquivo_entrada.csv", 
###   arquivo_saida = "nome_do_arquivo_saida.nex"         
### )