1. Leitura e preparação dos dados

df = read_xlsx("asma_espiro.xlsx") 
df = clean_names(df)
df$altura = df$altura/100

2. Dados demográficos

A amostra é composta por 577 crianças asmáticas, das quais 331 (57,4%) são do sexo masculino. A média de idade é de 9,5 ± 2,2 anos. A média de altura é de 1,37 ± 0,14 metros.

df %>%
  count(sexo) %>%
  mutate(percent = round(100 * n / sum(n), 1))
## # A tibble: 2 × 3
##    sexo     n percent
##   <dbl> <int>   <dbl>
## 1     1   331    57.4
## 2     2   246    42.6
df %>%
  summarise(
    idade_media = round(mean(idade, na.rm = TRUE), 1),
    idade_dp = round(sd(idade, na.rm = TRUE), 1),
    altura_media = round(mean(altura, na.rm = TRUE), 2),
    altura_dp = round(sd(altura, na.rm = TRUE), 2)
  )
## # A tibble: 1 × 4
##   idade_media idade_dp altura_media altura_dp
##         <dbl>    <dbl>        <dbl>     <dbl>
## 1         9.5      2.2         1.37      0.14

3. Seleção das variáveis e preparação inicial

df1 = df %>% select("id", "sexo", "altura", "idade", "cor", 
                    "cvf_pre", "vef1_pre", "vef1_cvf_pre",
                    "fef25_75_pre", "fef25_75_cvf_pre",
                    "cvf_pos", "vef1_pos", "vef1_cvf_pos",                  
                    "fef25_75_pos", "fef25_75_cvf_pos")

4. Cálculo dos z-scores e LLN (GLI)

z_gli_pre = zscore_GLIgl(age=df1$idade,height=df1$altura,
                gender = df1$sexo,
                FEV1 = df1$vef1_pre,
                FVC = df1$cvf_pre, 
                FEV1FVC = df1$vef1_cvf_pre)

z_gli_pos = zscore_GLIgl(age=df1$idade,height=df1$altura,
                   gender = df1$sexo,
                   FEV1 = df1$vef1_pos,
                   FVC = df1$cvf_pos, 
                   FEV1FVC = df1$vef1_cvf_pos)

lln_gli_pre = LLN_GLIgl(age=df1$idade,height=df1$altura,
                      gender = df1$sexo, param = c("FEV1","FVC","FEV1FVC"))

lln_gli_pos = LLN_GLIgl(age=df1$idade,height=df1$altura,
                        gender = df1$sexo,
                   param = c("FEV1","FVC","FEV1FVC"))

5. Adição de colunas calculadas

df1$zscore_vef1_pre_gli <- z_gli_pre$z.score.FEV1
df1$zscore_cvf_pre_gli <- z_gli_pre$z.score.FVC
df1$zscore_vef1_cvf_pre_gli <- z_gli_pre$z.score.FEV1FVC

df1$zscore_vef1_pos_gli <- z_gli_pos$z.score.FEV1
df1$zscore_cvf_pos_gli <- z_gli_pos$z.score.FVC
df1$zscore_vef1_cvf_pos_gli <- z_gli_pos$z.score.FEV1FVC

df1$lln_vef1_pre_gli <- lln_gli_pre$LLN.FEV1
df1$lln_cvf_pre_gli <- lln_gli_pre$LLN.FVC
df1$lln_vef1_cvf_pre_gli <- lln_gli_pre$LLN.FEV1FVC

df1$lln_vef1_pos_gli <- lln_gli_pos$LLN.FEV1
df1$lln_cvf_pos_gli <- lln_gli_pos$LLN.FVC
df1$lln_vef1_cvf_pos_gli <- lln_gli_pos$LLN.FEV1FVC

6. Integração e montagem dos dataframes finais

df1_gli <- df1 %>% select(id, contains("gli"))
df_filtered <- df %>%
  select(id, matches("quan|lln")) %>%
  select(-matches("fef"))
dff <- left_join(df1_gli, df_filtered, by = "id")

df3 <- df %>%
  left_join(dff, by = "id") %>%
  select(-ends_with(".y")) %>%
  rename_with(~ sub("\\.x$", "", .x), ends_with(".x"))

7. Classificação dos distúrbios

df4 <- df3 %>% select(id, cvf_pre, lln_cvf_pre_gli,
                      vef1_pre, lln_vef1_pre_gli,
                      vef1_cvf_pre, lln_vef1_cvf_pre_gli,
                      cvf_pos, lln_cvf_pos_gli, 
                      vef1_pos, lln_vef1_pos_gli,
                      vef1_cvf_pos, lln_vef1_cvf_pos_gli, 
                      cvf_lln_pre,cvf_lln_pos,
                      vef1_lln_pre, vef1_lln_pos,
                      vef1_cvf_lln_pre, vef1_cvf_lln_pos, 
                      cvf_z_pre, cvf_pos, zscore_cvf_pre_gli,zscore_cvf_pos_gli) %>% 
  mutate(
    cvf_normal_pre_gli = if_else(cvf_pre > lln_cvf_pre_gli, 1, 0),
    vef1_normal_pre_gli = if_else(vef1_pre > lln_vef1_pre_gli, 1, 0),
    vef1_cvf_normal_pre_gli = if_else(vef1_cvf_pre > lln_vef1_cvf_pre_gli, 1, 0),
    cvf_normal_pos_gli = if_else(cvf_pos > lln_cvf_pos_gli, 1, 0),
    vef1_normal_pos_gli = if_else(vef1_pos > lln_vef1_pos_gli, 1, 0),
    vef1_cvf_normal_pos_gli = if_else(vef1_cvf_pos > lln_vef1_cvf_pos_gli, 1, 0),
    cvf_normal_sbpt_pre = if_else(cvf_pre > cvf_lln_pre, 1, 0),
    vef1_normal_sbpt_pre = if_else(vef1_pre > vef1_lln_pre, 1, 0),
    vef1_cvf_normal_sbpt_pre = if_else(vef1_cvf_pre > vef1_cvf_lln_pre, 1, 0),
    cvf_normal_sbpt_pos = if_else(cvf_pos > cvf_lln_pos, 1, 0),
    vef1_normal_sbpt_pos = if_else(vef1_pos > vef1_lln_pos, 1, 0),
    vef1_cvf_normal_sbpt_pos = if_else(vef1_cvf_pos > vef1_cvf_lln_pos, 1, 0),
    cvf_des_gli_pre = if_else(zscore_cvf_pre_gli > 0.674, 1, 0),
    cvf_des_gli_pos = if_else(zscore_cvf_pos_gli > 0.674, 1, 0),
    cvf_des_sbpt_pre = if_else(cvf_pre > 0.674, 1, 0),
    cvf_des_sbpt_pos = if_else(cvf_pos > 0.674, 1, 0)
  )
df5 <- df4 %>%
  mutate(
    disturbio_pre_gli = case_when(
      vef1_normal_pre_gli == 0 & cvf_normal_pre_gli == 1 & vef1_cvf_normal_pre_gli == 1 ~ "Não específico",
      vef1_normal_pre_gli == 1 & cvf_des_gli_pre == 1 & vef1_cvf_normal_pre_gli == 0 ~ "Disanapsia",
      cvf_normal_pre_gli == 1 & vef1_cvf_normal_pre_gli == 0 ~ "Obstrutivo",
      vef1_normal_pre_gli == 0 & cvf_normal_pre_gli == 0 & vef1_cvf_normal_pre_gli == 1 ~ "Restritivo",
      cvf_normal_pre_gli == 0 & vef1_cvf_normal_pre_gli == 0 ~ "Misto",
      vef1_normal_pre_gli == 1 & cvf_normal_pre_gli == 1 & vef1_cvf_normal_pre_gli == 1 ~ "Normal",
      TRUE ~ "Não específico"
    ),
    disturbio_pos_gli = case_when(
      vef1_normal_pos_gli == 0 & cvf_normal_pos_gli == 1 & vef1_cvf_normal_pos_gli == 1 ~ "Não específico",
      vef1_normal_pos_gli == 1 & cvf_des_gli_pos == 1 & vef1_cvf_normal_pos_gli == 0 ~ "Disanapsia",
      cvf_normal_pos_gli == 1 & vef1_cvf_normal_pos_gli == 0 ~ "Obstrutivo",
      vef1_normal_pos_gli == 0 & cvf_normal_pos_gli == 0 & vef1_cvf_normal_pos_gli == 1 ~ "Restritivo",
      cvf_normal_pos_gli == 0 & vef1_cvf_normal_pos_gli == 0 ~ "Misto",
      vef1_normal_pos_gli == 1 & cvf_normal_pos_gli == 1 & vef1_cvf_normal_pos_gli == 1 ~ "Normal",
      TRUE ~ "Não específico"
    ),
    disturbio_sbpt_pre = case_when(
      vef1_normal_sbpt_pre == 0 & cvf_normal_sbpt_pre == 1 & vef1_cvf_normal_sbpt_pre == 1 ~ "Não específico",
      vef1_normal_sbpt_pre == 1 & cvf_des_sbpt_pre == 1 & vef1_cvf_normal_sbpt_pre == 0 ~ "Disanapsia",
      cvf_normal_sbpt_pre == 1 & vef1_cvf_normal_sbpt_pre == 0 ~ "Obstrutivo",
      vef1_normal_sbpt_pre == 0 & cvf_normal_sbpt_pre == 0 & vef1_cvf_normal_sbpt_pre == 1 ~ "Restritivo",
      cvf_normal_sbpt_pre == 0 & vef1_cvf_normal_sbpt_pre == 0 ~ "Misto",
      vef1_normal_sbpt_pre == 1 & cvf_normal_sbpt_pre == 1 & vef1_cvf_normal_sbpt_pre == 1 ~ "Normal",
      TRUE ~ "Não específico"
    ),
    disturbio_sbpt_pos = case_when(
      vef1_normal_sbpt_pos == 0 & cvf_normal_sbpt_pos == 1 & vef1_cvf_normal_sbpt_pos == 1 ~ "Não específico",
      vef1_normal_sbpt_pos == 1 & cvf_des_sbpt_pos == 1 & vef1_cvf_normal_sbpt_pos == 0 ~ "Disanapsia",
      cvf_normal_sbpt_pos == 1 & vef1_cvf_normal_sbpt_pos == 0 ~ "Obstrutivo",
      vef1_normal_sbpt_pos == 0 & cvf_normal_sbpt_pos == 0 & vef1_cvf_normal_sbpt_pos == 1 ~ "Restritivo",
      cvf_normal_sbpt_pos == 0 & vef1_cvf_normal_sbpt_pos == 0 ~ "Misto",
      vef1_normal_sbpt_pos == 1 & cvf_normal_sbpt_pos == 1 & vef1_cvf_normal_sbpt_pos == 1 ~ "Normal",
      TRUE ~ "Não específico"
    )
  )
df6 <- df5 %>%
  select(id, disturbio_pre_gli, disturbio_pos_gli, disturbio_sbpt_pre, disturbio_sbpt_pos)

8. Gráficos Comparativos

8.1 Gráfico Pré-BD

Na avaliação pré-broncodilatador (pré-BD), utilizando a equação de referência da GLI, 448 crianças (77,6%) foram classificadas como com função pulmonar normal, 31 (5,4%) apresentaram disanapsia, 60 (10,4%) com distúrbio obstrutivo, 19 (3,3%) com padrão restritivo, 15 (2,6%) como padrão não específico e 4 (0,7%) com padrão misto. Por outro lado, com a equação de referência da SBPT, 360 crianças (62,4%) foram classificadas como normais, 99 (17,2%) com disanapsia, 55 (9,5%) com padrão obstrutivo, 31 (5,4%) restritivo, 22 (3,8%) não específico e 10 (1,7%) com padrão misto.

df_plot <- df6 %>%
  select(id, disturbio_pre_gli, disturbio_sbpt_pre) %>%
  pivot_longer(
    cols = c(disturbio_pre_gli, disturbio_sbpt_pre),
    names_to = "sistema",
    values_to = "classificacao"
  ) %>%
  mutate(
    sistema = recode(sistema,
                     "disturbio_pre_gli" = "GLI",
                     "disturbio_sbpt_pre" = "SBPT")
  )

df_plot_sum <- df_plot %>%
  count(sistema, classificacao) %>%
  group_by(sistema) %>%
  mutate(percent = round(100 * n / sum(n), 1))

df_plot_sum <- df_plot_sum %>%
  group_by(classificacao) %>%
  mutate(total_n = sum(n)) %>%
  ungroup() %>%
  mutate(classificacao = fct_reorder(classificacao, total_n, .desc = TRUE))

ggplot(df_plot_sum, aes(x = classificacao, y = n, fill = sistema)) +
  geom_bar(stat = "identity", position = position_dodge(width = 0.9), color = "black") +
  geom_text(
    aes(label = paste0(percent, "%")),
    position = position_dodge(width = 0.9),
    vjust = -0.3,
    size = 3.5
  ) +
  scale_fill_manual(
    values = c("GLI" = "deepskyblue", "SBPT" = "darkorange")
  ) +
  scale_y_continuous(expand = expansion(mult = c(0, 0.05))) +  # <- Aqui está o ajuste
  labs(
    title = "Classificação dos Distúrbios Ventilatórios Pré-BD",
    x = "Classificação",
    y = "Frequência",
    fill = "Referência"
  ) +
  theme_classic() +
  theme(axis.text.x = element_text(angle = 0, hjust = 0.5))

8.2 Gráfico Pós-BD

Na avaliação pós-broncodilatador (pós-BD), utilizando a equação de referência da GLI, 508 crianças (88,0%) foram classificadas como com função pulmonar normal, 27 (4,7%) apresentaram padrão não específico, 8 (1,4%) disanapsia, 15 (2,6%) padrão restritivo, 17 (2,9%) padrão obstrutivo e 2 (0,3%) padrão misto. Com a equação da SBPT, 460 crianças (79,7%) foram classificadas como normais, 31 (5,4%) com padrão não específico, 44 (7,6%) com disanapsia, 24 (4,2%) com padrão restritivo, 14 (2,4%) obstrutivo e 4 (0,7%) com padrão misto.

df_plot <- df6 %>%
  select(id, disturbio_pos_gli, disturbio_sbpt_pos) %>%
  pivot_longer(
    cols = c(disturbio_pos_gli, disturbio_sbpt_pos),
    names_to = "sistema",
    values_to = "classificacao"
  ) %>%
  mutate(
    sistema = recode(sistema,
                     "disturbio_pos_gli" = "GLI",
                     "disturbio_sbpt_pos" = "SBPT")
  )

df_plot_sum <- df_plot %>%
  count(sistema, classificacao) %>%
  group_by(sistema) %>%
  mutate(percent = round(100 * n / sum(n), 1))

df_plot_sum <- df_plot_sum %>%
  group_by(classificacao) %>%
  mutate(total_n = sum(n)) %>%
  ungroup() %>%
  mutate(classificacao = fct_reorder(classificacao, total_n, .desc = TRUE))

ggplot(df_plot_sum, aes(x = classificacao, y = n, fill = sistema)) +
  geom_bar(stat = "identity", position = position_dodge(width = 0.9), color = "black") +
  geom_text(
    aes(label = paste0(percent, "%")),
    position = position_dodge(width = 0.9),
    vjust = -0.3,
    size = 3.5
  ) +
  scale_fill_manual(
    values = c("GLI" = "deepskyblue", "SBPT" = "darkorange")
  ) +
  scale_y_continuous(expand = expansion(mult = c(0, 0.05))) +  # <- ajuste do espaço inferior
  labs(
    title = "Classificação dos Distúrbios Ventilatórios Pós-BD",
    x = "Classificação",
    y = "Frequência",
    fill = "Referência"
  ) +
  theme_classic() +
  theme(axis.text.x = element_text(angle = 0, hjust = 0.5))

8.3 Gráfico conjunto (Pré e Pós-BD, com facetas)

df_plot <- df6 %>%
  select(id,
         disturbio_pre_gli, disturbio_sbpt_pre,
         disturbio_pos_gli, disturbio_sbpt_pos) %>%
  pivot_longer(
    cols = -id,
    names_to = "variavel",
    values_to = "classificacao"
  ) %>%
  mutate(
    sistema = case_when(
      grepl("gli", variavel) ~ "GLI",
      grepl("sbpt", variavel) ~ "SBPT"
    ),
    momento = case_when(
      grepl("pre", variavel) ~ "Pré-BD",
      grepl("pos", variavel) ~ "Pós-BD"
    )
  ) %>%
  mutate(
    momento = factor(momento, levels = c("Pré-BD", "Pós-BD"))
  ) %>%
  select(-variavel)

df_plot_sum <- df_plot %>%
  count(momento, sistema, classificacao) %>%
  group_by(momento, sistema) %>%
  mutate(percent = round(100 * n / sum(n), 1)) %>%
  group_by(momento, classificacao) %>%
  mutate(total_n = sum(n)) %>%
  ungroup() %>%
  mutate(classificacao = fct_reorder(classificacao, total_n, .desc = TRUE))

ggplot(df_plot_sum, aes(x = classificacao, y = n, fill = sistema)) +
  geom_bar(stat = "identity", position = position_dodge(width = 0.9), color = "black") +
  geom_text(
    aes(label = paste0(percent, "%")),
    position = position_dodge(width = 0.9),
    vjust = -0.3,
    size = 3.5
  ) +
  scale_fill_manual(
    values = c("GLI" = "deepskyblue", "SBPT" = "darkorange")
  ) +
  scale_y_continuous(expand = expansion(mult = c(0, 0.05))) +  # <- ajuste adicionado
  labs(
    title = "Classificação dos Distúrbios Ventilatórios",
    x = "Classificação",
    y = "Frequência",
    fill = "Referência"
  ) +
  theme_classic() +
  theme(
    axis.text.x = element_text(angle = 0, hjust = 0.5),
    strip.background = element_rect(fill = "grey90"),
    panel.spacing = unit(1.5, "lines"),
    panel.border = element_rect(color = "black", fill = NA, linewidth = 0.8)
  ) +
  facet_wrap(~ momento)