Last updated: 2025-07-29

Checks: 6 1

Knit directory: Importance-of-markers-for-QTL-detection-by-machine-learning-methods/

This reproducible R Markdown analysis was created with workflowr (version 1.7.1). The Checks tab describes the reproducibility checks that were applied when the results were created. The Past versions tab lists the development history.


The R Markdown file has unstaged changes. To know which version of the R Markdown file created these results, you’ll want to first commit it to the Git repo. If you’re still working on the analysis, you can ignore this warning. When you’re finished, you can run wflow_publish to commit the R Markdown file and build the HTML.

Great job! The global environment was empty. Objects defined in the global environment can affect the analysis in your R Markdown file in unknown ways. For reproduciblity it’s best to always run the code in an empty environment.

The command set.seed(20221222) was run prior to running the code in the R Markdown file. Setting a seed ensures that any results that rely on randomness, e.g. subsampling or permutations, are reproducible.

Great job! Recording the operating system, R version, and package versions is critical for reproducibility.

Nice! There were no cached chunks for this analysis, so you can be confident that you successfully produced the results during this run.

Great job! Using relative paths to the files within your workflowr project makes it easier to run your code on other machines.

Great! You are using Git for version control. Tracking code development and connecting the code version to the results is critical for reproducibility.

The results in this page were generated with repository version e2d6d68. See the Past versions tab to see a history of the changes made to the R Markdown and HTML files.

Note that you need to be careful to ensure that all relevant files for the analysis have been committed to Git prior to generating the results (you can use wflow_publish or wflow_git_commit). workflowr only checks the R Markdown file, but you know if there are other scripts or data files that it depends on. Below is the status of the Git repository when the results were generated:


Ignored files:
    Ignored:    .Rproj.user/
    Ignored:    analysis/figure/
    Ignored:    output/imp.tot.RData
    Ignored:    output/lddecay.tiff
    Ignored:    output/mod.rda

Unstaged changes:
    Modified:   analysis/GWAS.Rmd
    Modified:   output/acerto_erro.xlsx

Note that any generated files, e.g. HTML, png, CSS, etc., are not included in this status report because it is ok for generated content to have uncommitted changes.


These are the previous versions of the repository in which changes were made to the R Markdown (analysis/GWAS.Rmd) and HTML (docs/GWAS.html) files. If you’ve configured a remote Git repository (see ?wflow_git_remote), click on the hyperlinks in the table below to view the files as they were in that past version.

File Version Author Date Message
Rmd 1935974 WevertonGomesCosta 2025-07-28 add gwas .rmd and .html
html 1935974 WevertonGomesCosta 2025-07-28 add gwas .rmd and .html
Rmd afa31ca WevertonGomesCosta 2025-03-25 add results in gwas.rmd
Rmd 450b544 WevertonGomesCosta 2025-03-25 add files GWAS.Rmd, map.Rmd and snpsofinterest. Rdata

Importance Markers for QTL Detection by Machine Learning Methods

This document provides an overview of the analysis performed to assess the importance of markers for QTL detection using machine learning methods. The analysis includes data preparation, trait importance calculation, and visualization of results.

The traits importance data was obtained by script in Genomic-prediction-through-machine-learning-and-neural-networks-for-traits-with-epistasis

library(metan) # for the `metan` package
library(tidyverse) # for data manipulation and visualization
library(ggrepel) # for text label positioning
library(ggnewscale) # for multiple color scales in ggplot2
library(ggthemes) # for additional ggplot2 themes
library(gridExtra) # for arranging multiple ggplot2 plots

Data importantion

The results are stored in the imp.tot object. The snpsOfInterest object contains the SNPs of interest, and the results_gwas object contains the results of the GWAS analysis.

# Load the data
load("output/imp.tot.RData")
head(imp.tot)
# A tibble: 6 × 5
  Overall marker n.fold method variable
    <dbl> <chr>  <chr>  <chr>  <chr>   
1   100   601    1      MARS L 1       
2    91.6 1797   1      MARS L 1       
3    82.0 1396   1      MARS L 1       
4    73.3 2607   1      MARS L 1       
5    64.8 2196   1      MARS L 1       
6    54.7 1005   1      MARS L 1       
# Load the SNPs of interest and GWAS results
load("data/snpsOfInterest.RData")
head(snpsOfInterest)
  variable marker
1        1    201
2        1    602
3        1   1003
4        1   1404
5        1   1805
6        1   2206
# Load the GWAS results
load("output/results_gwas.rda")
head(results_gwas)
  SNP Chr Pos     P.value    MAF nobs H.B.P.Value    Effect variable method
1   1   1 0.0 0.006491210 0.4830 1000  0.02957927 0.3398233       V1    GLM
2   2   1 0.5 0.005261302 0.4810 1000  0.02544973 0.3467606       V1    GLM
3   3   1 1.0 0.005396649 0.4815 1000  0.02588584 0.3474298       V1    GLM
4   4   1 1.5 0.011629021 0.4825 1000  0.04447452 0.3137256       V1    GLM
5   5   1 2.0 0.010304126 0.4840 1000  0.04082959 0.3196014       V1    GLM
6   6   1 2.5 0.014412682 0.4840 1000  0.05192709 0.3027587       V1    GLM

Preparando os dados

Os dados de importância dos marcadores são organizados em um formato adequado para análise. A seguir, realizamos algumas transformações nos dados para facilitar a análise.

Preparando os dados de importância dos marcadores

O objeto imp.tot contém a importância dos marcadores para cada variável e método. A seguir, realizamos algumas transformações nos dados para facilitar a análise. Como temos 10 variáveis, cada uma com 4010 marcadores, e 11 métodos, para cada repetição e cada fold, vamos obter uma média dos dados.

# Preparando os dados de importância dos marcadores
imp.tot <- imp.tot %>%
  mutate(
    variable = as.numeric(variable),
    method = as.factor(method),
    marker = as.numeric(str_replace(marker, "V", ""))
  ) %>%
  group_by(variable, method, marker) %>%
  summarise(Overall = mean(Overall), .groups = "drop")

Preparando os resultados do GWAS

Os dados do GWAS são filtrados para incluir apenas os marcadores significativos, e o limiar de significância é definido com base no número total de marcadores.

# Definindo o limiar de significância
alpha <- 0.05
n.markers <- 4010
threshold <- alpha / n.markers

# Preparando os resultados do GWAS
results_gwas <- results_gwas %>%
  rename(marker = SNP, CHR = Chr) %>%
  mutate(
    variable = as.numeric(str_replace(variable, "V", "")),
    method = as.factor(method),
    CHR = as.numeric(CHR),
    marker = as.numeric(marker),
    Overall = -log10(P.value)
  )

# Filtrando os resultados significativos
results_gwas_sig <- results_gwas %>%
  filter(P.value < threshold) %>%
  mutate(sig = paste(variable, marker, sep = "_")) %>%
  droplevels() %>%
  select(variable, method, marker, CHR, Overall, sig)

Normalizando a importância dos marcadores para cada variável e método

Normalizamos a importância dos marcadores para cada variável e método, escalando os valores de Overall para um intervalo de 0 a 10. Isso facilita a comparação entre diferentes métodos e variáveis.

# Normalizando a importância dos marcadores para cada variável e método
methods <- unique(imp.tot$method)
variables <- unique(imp.tot$variable)
normalized_imp <- imp.tot %>%
  group_by(method, variable) %>%
  mutate(Overall_res = scales::rescale(Overall, to = c(0, 10), finite = F)) %>%
  ungroup()

Criando regiões ao redor dos SNPs de interesse

Primeiro criamos dois data frames, reg1 e reg2, que contêm os marcadores ao redor de cada SNP de interesse. Em seguida, unimos esses data frames para criar o data frame region, que contém as regiões ao redor dos SNPs de interesse.

# Criando os data frames 'reg1' e 'reg2' com os marcadores ao redor de cada SNP de interesse
reg1 <- snpsOfInterest %>%
  group_by(variable) %>%
  mutate(region_markers = row_number()) %>%
  ungroup()

# Adicionando 8 à variável 'variable' para criar o segundo data frame
reg2 <- snpsOfInterest %>%
  mutate(variable = variable + 8) %>% 
  group_by(variable) %>%
  mutate(region_markers = row_number()) %>%
  ungroup()

# Agora, criamos o data frame 'region' com os marcadores ao redor de cada SNP de interesse
distance <- 5

# Unindo os data frames 'reg1' e 'reg2' e criando as regiões ao redor dos SNPs de interesse
region <- reg1 %>%
  full_join(reg2) %>%
  rowwise() %>%
  mutate(marker = list(seq(marker - distance, marker + distance))) %>%
  ungroup() %>%
  unnest(cols = marker) %>%
  filter(variable %in% c(1:5, 9:13)) %>%
  droplevels()

Contando o número de genes em cada região

Para cada região, contamos o número de genes presentes. Isso nos ajuda a entender a densidade de marcadores em cada região do QTL.

# Contando o número de genes em cada região
ngenes_region <- region %>%
  group_by(variable) %>%
  summarise(ngenes_region = n(), .groups = "drop") %>%
  mutate(variable = factor(variable, labels = c(1:10)))

Calculando a importância média dos marcadores

Os efeitos médios dos marcadores são calculados para cada variável e método, permitindo uma análise comparativa da importância dos marcadores entre diferentes métodos de machine learning e a atribuição de significância aos marcadores.

# Calculando a importância média dos marcadores para cada variável e método
effects_markers <- normalized_imp %>%
  group_by(variable, method) %>%
  summarise(effects_markers = mean(Overall_res), .groups = "drop")

Associando os marcadores às regiões do QTL

Nesta seção, associamos os marcadores às regiões do QTL, utilizando os data frames normalized_imp, results_gwas, effects_markers e region. A seguir, criamos o data frame plot_data, que contém informações sobre os marcadores, suas importâncias, os resultados do GWAS e as regiões de interesse.

Criando o data frame plot_data

O data frame plot_data é criado para associar os marcadores às regiões do QTL, incluindo informações sobre a importância dos marcadores, os resultados do GWAS e as regiões de interesse. Para isso , utilizamos a função mutate para adicionar uma coluna CHR que indica o cromossomo ao qual cada marcador pertence. Em seguida, unimos os data frames normalized_imp, results_gwas, effects_markers e region para criar o data frame final plot_data.

Além disso, adicionamos informações sobre os marcadores e regiões, como se o marcador é destacado (is_highlight) ou anotado (is_annotate), e criamos variáveis adicionais para facilitar a análise.

# Associando os marcadores às regiões do QTL
plot_data <- normalized_imp %>%
  mutate(
    CHR = case_when(
      marker <= 401 ~ 1,
      marker <= 802 ~ 2,
      marker <= 1203 ~ 3,
      marker <= 1604 ~ 4,
      marker <= 2005 ~ 5,
      marker <= 2406 ~ 6,
      marker <= 2807 ~ 7,
      marker <= 3208 ~ 8,
      marker <= 3609 ~ 9,
      TRUE ~ 10
    )
  ) %>%
  full_join(results_gwas) %>%
  full_join(effects_markers) %>%
  full_join(region)

# Adicionando informações sobre os marcadores e regiões
plot_data <- plot_data %>%
  mutate(
    sig = paste(variable, marker, sep = "_"),
    is_highlight = if_else(!is.na(region_markers), "yes", "no"),
    is_annotate = case_when(
      Overall_res > effects_markers & method != "GLM" ~ "yes",
      method == "GLM" & sig %in% results_gwas_sig$sig ~ "yes",
      TRUE ~ "no",
    )
  )

Criando variáveis adicionais

Para facilitar a análise, criamos variáveis adicionais no data frame plot_data, como herd, ngenes, created, e is_high_anno. Essas variáveis ajudam a categorizar os dados e a identificar as características dos métodos e das regiões analisadas.

# Criando variáveis adicionais no data frame plot_data
plot_data <- plot_data %>%
  mutate(
    herd = factor(if_else(variable < 9, "50%", "80%")),
    ngenes = factor(
      case_when(
        variable %in% c(1, 9) ~ 8,
        variable %in% c(2, 10) ~ 40,
        variable %in% c(3, 11) ~ 80,
        variable %in% c(4, 12) ~ 120,
        variable %in% c(5, 13) ~ 240,
        variable %in% c(6, 14) ~ 480,
        variable %in% c(7, 15) ~ 88,
        variable %in% c(8, 16) ~ 160
      )
    ),
    created = factor(if_else(
      ngenes %in% c(88, 160), "Simulated modified", "Simulated"
    )),
    is_high_anno = case_when(
      is_highlight == "yes" & is_annotate == "yes" ~ 1,
      is_highlight == "yes" & is_annotate == "no" ~ 2,
      is_highlight == "no" & is_annotate == "yes" ~ 3,
      TRUE ~ 4
    ),
    variable = factor(variable)
  )

# Reordenando os métodos
levels(plot_data$method) <-  c("BAG",
                               "BO",
                               "DT",
                               "G-BLUP",
                               "MARS 3",
                               "MARS 1",
                               "MARS 2",
                               "MLP",
                               "RBF",
                               "RF",
                               "GLM")

# Reordenando os métodos para facilitar a visualização
plot_data <- plot_data %>%
  mutate(method =  fct_relevel(method, sort))

Filtrando apenas as variáveis simuladas

Algumas variáveis foram criadas para simular diferentes cenários de herdabilidade e número de genes. Para a análise, vamos focar apenas nas variáveis simuladas, excluindo aquelas que não são relevantes para o nosso estudo.

# Filtrando apenas as variáveis simuladas
plot_data <- plot_data %>%
  filter(created == "Simulated" & ngenes != 480) %>%
  #filter(!(method %in% c("RBF", "MLP", "G-BLUP"))) %>%
  droplevels()

# Reordenando as variáveis para facilitar a visualização
levels(plot_data$variable) <-
  c("1", "2", "3", "4", "5", "6", "7", "8", "9", "10")

Análise de Coincidência

Nesta seção, calculamos o índice de coincidência entre os marcadores anotados e os marcadores significativos do GWAS. A análise é feita para cada variável, método e região dos marcadores.

Contando os marcadores anotados

Primeiro, filtramos os dados para obter apenas os marcadores anotados e contamos quantos marcadores estão presentes em cada região.

# Contando os marcadores anotados
ver <- plot_data %>%
  filter(is_annotate == "yes") %>%
  group_by(variable, method, CHR, region_markers) %>%
  summarise(n = n(), .groups = "drop")

Separando acertos e erros

A seguir, separamos os acertos (marcadores anotados que estão presentes nas regiões) e os erros (marcadores anotados que não estão presentes nas regiões).

# Separando acertos e erros
certo <- ver %>%
  filter(region_markers != "NA") %>%
  group_by(variable, method) %>%
  reframe(n = n)

# Contando os acertos
acerto <- certo %>%
  count(variable, method, name = "acerto")

# Contando os erros
errado <- ver %>%
  filter(is.na(region_markers)) %>%
  group_by(variable, method, CHR, region_markers) %>%
  reframe("erro" = n)

# Agrupando os erros por variável e método
erro <- errado %>%
  group_by(variable, method) %>%
  summarise(erro = sum(erro), .groups = "drop")

Unindo acertos e erros e calculando os índices

O data frame coinc é criado unindo os acertos e erros, e adicionando informações sobre o número de genes em cada região. Em seguida, calculamos os índices de Poder de Decisão (PD), Falso Positivo (FP), Precisão, Especificidade e F1 Score para cada variável e método.

# Unindo acertos e erros e calculando os índices
coinc <- full_join(acerto, erro) %>%
  full_join(ngenes_region) %>%
  mutate(
    acerto = replace_na(acerto, 0),
    erro = replace_na(erro, 0),
    ngenes = case_when(
      variable %in% c("1", "6") ~ 8,
      variable %in% c("2", "7") ~ 40,
      variable %in% c("3", "8") ~ 80,
      variable %in% c("4", "9") ~ 120,
      variable %in% c("5", "10") ~ 240
    ),
    herd = if_else(as.numeric(variable) < 6, "h² = 0.50", "h² = 0.80"),
    # Poder de Decisão (PD) = Sensibilidade
    PD = round((acerto / ngenes) * 100, 2),
    # Falso Positivo (FP)
    FP = round((erro / (
      n.markers - ngenes_region
    )) * 100, 2),
    # Precisão
    Precision = round(acerto / (acerto + erro) * 100, 2),
    # Adicionando os novos índices:
    Specificity = round((((n.markers - ngenes_region) - erro
    ) / (
      n.markers - ngenes_region
    )) * 100, 2),
    # Média harmônica entre precisão e Poder de Decisão ,
    `F1 Score` = round(2 * (Precision * PD) / (Precision + PD), 2),
  ) %>%
  filter(!(method %in% c("RBF", "MLP", "G-BLUP"))) %>%
  droplevels()

# Selecionando as colunas relevantes para o resultado final
acerto_erro <- coinc %>%
  select(variable, method, acerto, erro)

# Calculando a média de acertos e erros por variável e método
coinc %>%
  select(variable, method, PD) %>%
  pivot_wider(names_from = variable, values_from = PD)
# A tibble: 8 × 11
  method   `1`   `2`   `3`   `4`   `5`   `6`   `7`   `8`   `9`  `10`
  <fct>  <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 BAG    100    90    91.2  91.7  83.8 100    97.5  90    87.5  85.4
2 BO     100   100    96.2  93.3  92.1 100   100    95    95.8  87.5
3 DT     100    42.5  41.2  50    44.2 100    67.5  41.2  40.8  41.2
4 GLM     62.5  57.5  72.5  81.7  94.2  87.5  92.5  98.8  97.5  99.6
5 MARS 1 100    15    12.5  11.7  12.5 100    17.5  13.8  14.2  13.3
6 MARS 2 100    27.5  18.8  22.5  30   100    52.5  41.2  30.8  37.5
7 MARS 3 100    57.5  47.5  54.2  66.7 100    72.5  67.5  66.7  68.3
8 RF     100    82.5  90    86.7  81.7 100    95    86.2  85.8  82.1

Visualização dos Resultados

Para visualizar os índices de coincidência, utilizamos gráficos de calor (heatmaps) para representar os valores de Poder de Decisão (PD), Precisão, Especificidade e Falso positivos. A seguir, apresentamos os gráficos para cada índice.

Poder de Decisão (PD) e Precisão

Para visualizar o Poder de Decisão (PD) e a Precisão, utilizamos um gráfico de calor onde os valores são representados por cores. Os métodos são organizados em ordem decrescente de importância, e as regiões são facetadas por herdabilidade.

# Visualizando os índices de coincidência
coinc %>%
  select(method, ngenes, herd, PD, Precision) %>%
  pivot_longer(cols = 4:5) %>%
  mutate(method = factor(method, levels = rev(sort(unique(method))))) %>%
  ggplot(aes(
    x = factor(ngenes),
    y = method,
    fill = value
  )) +
  # Adicionando os tiles (blocos da matriz)
  geom_tile(color = "black") +
  # Ajustando a escala de preenchimento
  scale_fill_gradient2(
    low = "white",
    mid = "yellow",
    high = "red",
    midpoint = 50,
    # 100 / 2 simplifica para 50
    limits = c(0, 100),
    space = "Lab",
    name = "Value"
  ) +
  # Facetando por 'herd' (herdabilidade)
  facet_wrap(name ~ herd, nrow = 1) +
  # Aplicando tema minimalista com tamanho de texto base
  theme_bw() +
  # Ajustando elementos do tema
  theme(
    axis.text.x = element_text(vjust = 1, hjust = 0.5),
    axis.title.y = element_blank(),
    panel.grid.major = element_blank(),
    axis.ticks = element_blank(),
    legend.position = "top",
    legend.direction = "horizontal",
    #    legend.title = element_text(size = 12),
    #    legend.text = element_text(size = 10)
  ) +
  # Fixando a proporção dos eixos
  coord_fixed() +
  # Adicionando os valores de PD como texto nos tiles
  geom_text(aes(label = value), color = "black") +
  # Ajustando o título do eixo X
  labs(x = "Number of Genes")

Falso Positivo (FP) e Especificidade

Para visualizar o Falso Positivo (FP) e a Especificidade, utilizamos um gráfico de calor semelhante ao anterior, onde os valores são representados por cores. Os métodos são organizados em ordem decrescente de importância, e as regiões são facetadas por herdabilidade.

coinc %>%
  select(method, ngenes, herd, FP, Specificity) %>%
  pivot_longer(cols = 4:5) %>%
  mutate(method = factor(method, levels = rev(sort(unique(
    method
  ))))) %>%
  ggplot(aes(
    x = factor(ngenes),
    y = method,
    fill = value
  )) +
  # Adicionando os tiles (blocos da matriz)
  geom_tile(color = "black") +
  # Ajustando a escala de preenchimento
  scale_fill_gradient2(
    low = "white",
    mid = "yellow",
    high = "red",
    midpoint = 50,
    # 100 / 2 simplifica para 50
    limits = c(0, 100),
    space = "Lab",
    name = "Value"
  ) +
  # Facetando por 'herd' (herdabilidade)
  facet_wrap(name ~ herd, nrow = 1) +
  # Aplicando tema minimalista com tamanho de texto base
  theme_bw() +
  # Ajustando elementos do tema
  theme(
    axis.text.x = element_text(vjust = 1, hjust = 0.5),
    axis.title.y = element_blank(),
    panel.grid.major = element_blank(),
    axis.ticks = element_blank(),
    legend.position = "top",
    legend.direction = "horizontal",
    #    legend.title = element_text(size = 12),
    #    legend.text = element_text(size = 10)
  ) +
  # Fixando a proporção dos eixos
  coord_fixed() +
  # Adicionando os valores de PD como texto nos tiles
  geom_text(aes(label = value), color = "black") +
  # Ajustando o título do eixo X
  labs(x = "Number of Genes")

F1 Score

O índice F1 Score é uma métrica que combina a precisão e o Poder de Decisão (PD) em um único valor, permitindo uma avaliação mais equilibrada do desempenho dos métodos. A seguir, apresentamos o gráfico de calor para o F1 Score.

coinc %>%
  select(method, ngenes, herd, `F1 Score`) %>%
  pivot_longer(cols = 4) %>%
  mutate(method = factor(method, levels = rev(sort(unique(
    method
  ))))) %>%
  ggplot(aes(
    x = factor(ngenes),
    y = method,
    fill = value
  )) +
  # Adicionando os tiles (blocos da matriz)
  geom_tile(color = "black") +
  # Ajustando a escala de preenchimento
  scale_fill_gradient2(
    low = "white",
    mid = "yellow",
    high = "red",
    midpoint = 50,
    # 100 / 2 simplifica para 50
    limits = c(0, 100),
    space = "Lab",
    name = "Value"
  ) +
  # Facetando por 'herd' (herdabilidade)
  facet_wrap(name ~ herd, nrow = 1) +
  # Aplicando tema minimalista com tamanho de texto base
  theme_bw() +
  # Ajustando elementos do tema
  theme(
    axis.text.x = element_text(vjust = 1, hjust = 0.5),
    axis.title.y = element_blank(),
    panel.grid.major = element_blank(),
    axis.ticks = element_blank(),
    legend.position = "right",
    legend.direction = "vertical",
    #    legend.title = element_text(size = 12),
    #    legend.text = element_text(size = 10)
  ) +
  # Fixando a proporção dos eixos
  coord_fixed() +
  # Adicionando os valores de PD como texto nos tiles
  geom_text(aes(label = value), color = "black") +
  # Ajustando o título do eixo X
  labs(x = "Number of Genes")

Conclusão

A análise realizada demonstra a importância dos marcadores para a detecção de QTLs utilizando métodos de machine learning. Os resultados mostram que, embora alguns métodos apresentem alta sensibilidade na detecção de regiões associadas a QTLs, eles também podem gerar um número elevado de falsos positivos.

Além disso, a análise de coincidência revela que os métodos MARS e G-BLUP apresentam um bom equilíbrio entre Poder de Decisão e Especificidade, enquanto outros métodos, como MLP e RBF, tendem a gerar muitos falsos positivos.

De forma geral, embora redes neurais e G BLUP sejam sensíveis ao captar zonas ligadas, sua baixa especificidade compromete a aplicabilidade prática. Dentre as demais metodologias, os protocolos MARS se destacam pelo equilíbrio entre detecção e precisão, especialmente em cenários de alta herdabilidade e múltiplos QTLs.


sessionInfo()
R version 4.4.1 (2024-06-14 ucrt)
Platform: x86_64-w64-mingw32/x64
Running under: Windows 11 x64 (build 26100)

Matrix products: default


locale:
[1] LC_COLLATE=Portuguese_Brazil.utf8  LC_CTYPE=Portuguese_Brazil.utf8   
[3] LC_MONETARY=Portuguese_Brazil.utf8 LC_NUMERIC=C                      
[5] LC_TIME=Portuguese_Brazil.utf8    

time zone: America/Sao_Paulo
tzcode source: internal

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
 [1] gridExtra_2.3    ggthemes_5.1.0   ggnewscale_0.5.2 ggrepel_0.9.6   
 [5] lubridate_1.9.4  forcats_1.0.0    stringr_1.5.1    dplyr_1.1.4     
 [9] purrr_1.1.0      readr_2.1.5      tidyr_1.3.1      tibble_3.3.0    
[13] ggplot2_3.5.2    tidyverse_2.0.0  metan_1.19.0    

loaded via a namespace (and not attached):
 [1] gtable_0.3.6        xfun_0.52           bslib_0.9.0        
 [4] GGally_2.2.1        lattice_0.22-7      tzdb_0.5.0         
 [7] numDeriv_2016.8-1.1 mathjaxr_1.8-0      vctrs_0.6.5        
[10] tools_4.4.1         Rdpack_2.6.4        generics_0.1.4     
[13] pkgconfig_2.0.3     Matrix_1.7-0        RColorBrewer_1.1-3 
[16] lifecycle_1.0.4     compiler_4.4.1      farver_2.1.2       
[19] git2r_0.36.2        ggforce_0.5.0       lmerTest_3.1-3     
[22] httpuv_1.6.16       htmltools_0.5.8.1   sass_0.4.10        
[25] yaml_2.3.10         later_1.4.2         pillar_1.11.0      
[28] nloptr_2.2.1        jquerylib_0.1.4     whisker_0.4.1      
[31] MASS_7.3-60.2       cachem_1.1.0        reformulas_0.4.1   
[34] boot_1.3-30         nlme_3.1-168        ggstats_0.10.0     
[37] tidyselect_1.2.1    digest_0.6.37       stringi_1.8.7      
[40] labeling_0.4.3      splines_4.4.1       polyclip_1.10-7    
[43] rprojroot_2.0.4     fastmap_1.2.0       grid_4.4.1         
[46] cli_3.6.5           magrittr_2.0.3      patchwork_1.3.1    
[49] utf8_1.2.6          withr_3.0.2         scales_1.4.0       
[52] promises_1.3.3      writexl_1.5.4       timechange_0.3.0   
[55] rmarkdown_2.29      lme4_1.1-37         workflowr_1.7.1    
[58] hms_1.1.3           evaluate_1.0.4      knitr_1.50         
[61] rbibutils_2.3       rlang_1.1.6         Rcpp_1.1.0         
[64] glue_1.8.0          tweenr_2.0.3        rstudioapi_0.17.1  
[67] minqa_1.2.8         jsonlite_2.0.0      R6_2.6.1           
[70] plyr_1.8.9          fs_1.6.6