Ce script a servi à développer le prototype de l’outil de suivi de la consommation médicamenteuse en Nouvelle-Aquitaine et en France métropolitaine.

# Importation du fichier de données : ----
data <- read.csv("NB_2023_atc3_age_sexe_reg.CSV", sep=";")
# library(readxl)
# data2 <- read_excel("vrai2.xlsx")
# IMportation des packages :  ----
library(dplyr)
library(gtsummary)
library(reactable)
library(epiR)
library(shiny)
library(shinydashboard)
library(rsconnect)


# Data management: ---- 
summary(data)
data <- na.omit(data)
data$age <- as.factor(data$age)
data$sexe <- as.factor(data$sexe)
data$BEN_REG <- as.factor(data$BEN_REG)
sum(is.na(data)) # pas de données manquantes 
unique(data$BEN_REG)
unique(data$age)
summary(data)
data$l_atc3 <- iconv(data$l_atc3, from = "latin1", to = "UTF-8")

# Gestion des données aberrantes : 
data <- data[data$age != 99, ]
summary(data$age)
data <- data[data$BEN_REG != 0,]
data <- data[data$BEN_REG != 99,] 
data <- data[data$BEN_REG != 5,] 
data <- data[data$sexe != 9, ] 
summary(data)
unique(data$age)
summary(data$BEN_REG)

# Nouvelle-Aquitaine ----
# TAB3 avec les variables importantes
TAB3 <- data %>% 
  select(ATC3, l_atc3, nbc, sexe, BEN_REG, age) %>% 
  group_by(age, ATC3) 

# Création des vecteurs  : 
pop_hommes_ensemble <- numeric(nrow(TAB3)) 
pop_femmes_ensemble <- numeric(nrow(TAB3))

# Définir les populations selon l'âge et le sexe de Nouvelle - Aquitaine 
# Celon les données de l'Insee
for (i in 1:nrow(TAB3)) {
  if (TAB3$age[i] == 0) {
    if (TAB3$sexe[i] == 1) {  # Homme
      pop_hommes_ensemble[i] <- 661165
    } else if (TAB3$sexe[i] == 2) {  # Femme
      pop_femmes_ensemble[i] <- 628020
    }
  } else if (TAB3$age[i] == 20) {
    if (TAB3$sexe[i] == 1) {  
      pop_hommes_ensemble[i] <- 1415320
    } else if (TAB3$sexe[i] == 2) {  
      pop_femmes_ensemble[i] <- 1455724
    }
  } else if (TAB3$age[i] == 60) {
    if (TAB3$sexe[i] == 1) {  
      pop_hommes_ensemble[i] <- 865152
    } else if (TAB3$sexe[i] == 2) {  
      pop_femmes_ensemble[i] <- 1084984
    }
  } else {
    pop_hommes_ensemble[i] <- NA
    pop_femmes_ensemble[i] <- NA
  }
}  


TAB3$pop_hommes_ensemble <- pop_hommes_ensemble
TAB3$pop_femmes_ensemble <- pop_femmes_ensemble

# Calcul de la prévalence brute en fonction de l'âge chez les hommes et les femmes en Nouvelle-Aquitaine
prevalence_brute <- numeric(nrow(TAB3)) 

for (i in 1:nrow(TAB3)) {
  if (TAB3$age[i] %in% c(0, 20, 60) & TAB3$BEN_REG[i] == 75) {  
    if (TAB3$sexe[i] == 1) {  # Si homme
      prevalence_brute[i] <- (TAB3$nbc[i] / pop_hommes_ensemble[i]) * 100000
    } else if (TAB3$sexe[i] == 2) {  # Si femme
      prevalence_brute[i] <- (TAB3$nbc[i] / pop_femmes_ensemble[i]) * 100000
    }
  } else {
    prevalence_brute[i] <- NA  # NA pour les autres cas
  }
}  
TAB3$prevalence_brute <- prevalence_brute

# Standardisation directe : 
# Création des vecteurs, suivant la répartition de la population en France 
# Chez les femmes
w1H <- (7854105/65834837) # 0 - 19 ans
w2H <- (15963230/65834837) # 20 - 59 ans 
w3H <- ( 8066487/65834837) # + 60 ans 

# Chez les hommes
w1F <- (7464504/65834837) # 0 - 19 ans
w2F <- (16343686/65834837) # 20 - 59 ans 
w3F <- (10142825/65834837) # + 60 ans 


G_NV_standardise_classe_age <- numeric(nrow(TAB3))
for (i in 1:nrow(TAB3)) {
  if (TAB3$sexe[i] == 1) {
    # Si homme
    if (TAB3$age[i] == 0) {
      G_NV_standardise_classe_age[i] <- TAB3$prevalence_brute[i] * w1H
    } else if (TAB3$age[i] == 20) {
      G_NV_standardise_classe_age[i] <- TAB3$prevalence_brute[i] * w2H
    } else if (TAB3$age[i] == 60) {
      G_NV_standardise_classe_age[i] <- TAB3$prevalence_brute[i] * w3H
    } else {
      G_NV_standardise_classe_age[i] <- NA
    }
  } else if (TAB3$sexe[i]  == 2) {
    # Si femme
    if (TAB3$age[i] == 0) {
      G_NV_standardise_classe_age[i] <- TAB3$prevalence_brute[i] * w1F
    } else if (TAB3$age[i] == 20) {
      G_NV_standardise_classe_age[i] <- TAB3$prevalence_brute[i] * w2F
    } else if (TAB3$age[i] == 60) {
      G_NV_standardise_classe_age[i] <- TAB3$prevalence_brute[i] * w3F
    } else {
      G_NV_standardise_classe_age[i] <- NA
    }
  } else {
    G_NV_standardise_classe_age[i] <- NA
  }
}
TAB3$G_NV_standardise_classe_age <- G_NV_standardise_classe_age

# Ensuite on fait le total des classes d'âges :  
# Prévalence globale par classe de médicaments 
G_prevalence_somme_par_medicament <- TAB3 %>%
  group_by(ATC3) %>%                      
  summarise(
    G_NV_prevalence_totale = sum(G_NV_standardise_classe_age, na.rm = TRUE)   
  ) 
TAB3 <- TAB3  %>%
  left_join(G_prevalence_somme_par_medicament, by = "ATC3")

# Calcul de l'indice supplémentaire (SMR) ----
pop_hommes_ensemble_bis <- numeric(nrow(TAB3)) 
pop_femmes_ensemble_bis <- numeric(nrow(TAB3))

# Définir les populations selon l'âge et le sexe mais en FRANCE ( donc par rapport aux effectifs total France) : 
for (i in 1:nrow(TAB3)) {
  if (TAB3$age[i] == 0) {
    if (TAB3$sexe[i] == 1) {  # Homme
      pop_hommes_ensemble_bis[i] <- 7854105
    } else if (TAB3$sexe[i] == 2) {  # Femme
      pop_femmes_ensemble_bis[i] <- 7464504
    }
  } else if (TAB3$age[i] == 20) {
    if (TAB3$sexe[i] == 1) {  # Homme
      pop_hommes_ensemble_bis[i] <- 15963230
      
    } else if (TAB3$sexe[i] == 2) {  # Femme
      pop_femmes_ensemble_bis[i] <- 16343686
    }
  } else if (TAB3$age[i] == 60) {
    if (TAB3$sexe[i] == 1) {  # Homme
      pop_hommes_ensemble_bis[i] <- 8066487
    } else if (TAB3$sexe[i] == 2) {  # Femme
      pop_femmes_ensemble_bis[i] <- 10142825
    }
  } else {
    pop_hommes_ensemble_bis[i] <- NA
    pop_femmes_ensemble_bis[i] <- NA
  }
}  

somme_nbc_table <- TAB3 %>%
  group_by(ATC3, sexe, age) %>%
  summarise(somme_nbc = sum(nbc, na.rm = TRUE), .groups = "drop")
TAB3 <- left_join(TAB3, somme_nbc_table, by = c("ATC3", "sexe", "age"))

prev_FR <- numeric(nrow(TAB3))
for (i in 1:nrow(TAB3)) {
  if (TAB3$age[i] %in% c(0, 20, 60)) {  
    if (TAB3$sexe[i] == 1) {  # Si homme
      prev_FR[i] <- (TAB3$somme_nbc[i]/ pop_hommes_ensemble_bis[i]) * 100000
    } else if (TAB3$sexe[i] == 2) {  # Si femme
      prev_FR[i] <- (TAB3$somme_nbc[i] / pop_femmes_ensemble_bis[i]) * 100000
    }
  } else {
    prev_FR[i] <- NA  
  }
}  
TAB3$prev_FR <- prev_FR

# Application des taux à la population de Nouvelle-Aquitaine par sexe et âge : 
# ( donc on renseigne les valeurs de Nouvelle-Aquitaine)

w1HNA <- 661165 # 0 - 19 ans
w2HNA <- 1415320 # 20 - 59 ans 
w3HNA <- 865152 # + 60 ans 

w1FNA <- 628020 # 0 - 19 ans
w2FNA <- 1455724 # 20 - 59 ans 
w3FNA <- 1084984 # + 60 ans 

nb_attendu <- numeric(nrow(TAB3))
for (i in 1:nrow(TAB3)) {
  if (TAB3$sexe[i] == 1) {
    # Si homme
    if (TAB3$age[i] == 0) {
      nb_attendu[i] <- (TAB3$prev_FR[i] / 100000) * w1HNA
    } else if (TAB3$age[i] == 20) {
      nb_attendu[i] <- (TAB3$prev_FR[i] / 100000) * w2HNA
    } else if (TAB3$age[i] == 60) {
      nb_attendu[i] <- (TAB3$prev_FR[i] / 100000) * w3HNA
    } else {
      nb_attendu[i] <- NA
    }
  } else if (TAB3$sexe[i]  == 2) {
    # Si femme
    if (TAB3$age[i] == 0) {
      nb_attendu[i] <- (TAB3$prev_FR[i] / 100000) * w1FNA
    } else if (TAB3$age[i] == 20) {
      nb_attendu[i] <- (TAB3$prev_FR[i] / 100000) * w2FNA
    } else if (TAB3$age[i] == 60) {
      nb_attendu[i] <- (TAB3$prev_FR[i] / 100000) * w3FNA
    } else {
      nb_attendu[i] <- NA
    }
  } else {
    nb_attendu[i] <- NA
  }
}
TAB3$nb_attendu <- nb_attendu
View(TAB3)

# Ensuite calcule du ratio standardisé : observé / attendu 
# Calcul de la prévalence brute par classe de médicaments (ATC3)

# Calcul des sommes et du SMR par classe ATC3
# somme_prevalence_brute_bis <- TAB3 %>%
#   #filter(BEN_REG == 75) %>%    # filtrer ici pour ne garder que la région Nouvelle-Aquitaine (exemple)
#   group_by(ATC3) %>%
#   filter(BEN_REG==75) %>% 
#   summarise(
#     somme_prevalence_brute = sum(prevalence_brute, na.rm = TRUE)/ 6110365,
#     somme_nb_attendu = sum(nb_attendu, na.rm = TRUE),
#     SMR = somme_prevalence_brute / somme_nb_attendu)
# 
# TAB3 <- TAB3  %>%
#   left_join(somme_prevalence_brute_bis, by = "ATC3")
# View(somme_prevalence_brute_bis)

pop_totale_NA <- 6110365 # Population totale Nouvelle-Aquitaine (toutes classes d'âge et sexe confondu) 
# Calcul du nombre de cas observés par classes ATC
somme_nbc_ATC3 <- TAB3 %>%
  filter(BEN_REG == 75) %>%
  group_by(ATC3) %>%
  summarise(
    total_nbc = sum(nbc, na.rm = TRUE),
    somme_prevalence_brute = (total_nbc / pop_totale_NA) * 100000
  )

# somme_nb_attendu par ATC3 en Nouvelle-Aquitaine
somme_nb_attendu_ATC3 <- TAB3 %>%
  filter(BEN_REG == 75) %>%
  group_by(ATC3) %>%
  summarise(somme_nb_attendu = sum(nb_attendu, na.rm = TRUE))

# Jointure des tables
TAB3 <- TAB3 %>%
  left_join(somme_nbc_ATC3, by = "ATC3") %>%
  left_join(somme_nb_attendu_ATC3, by = "ATC3") %>%
  mutate(SMR = total_nbc / somme_nb_attendu)
View(TAB3)
# France : ---- 
# Calcul de la prévalence par classe de médicaments (ATC3)
pop_totale_FR <- 65834837
Fprevalence_brute <- TAB3 %>%
  group_by(ATC3) %>%
  summarise(nbc_total_FR = sum(nbc, na.rm = TRUE), .groups = "drop") %>%
  mutate(prevalence_brute_FR = (nbc_total_FR / pop_totale_FR) * 100000)

TAB3 <- TAB3  %>%
  left_join(Fprevalence_brute, by = "ATC3")


# Ecart relatif : ----
ecart_relatif<- numeric(nrow(TAB3))
for (i in 1:nrow(TAB3)) {
  if (TAB3$age[i] %in% c(0, 20, 60)) {
    ecart_relatif[i] = ((TAB3$G_NV_prevalence_totale[i] - TAB3$prevalence_brute_FR[i] ) / TAB3$prevalence_brute_FR[i]) 
  } else {
    ecart_relatif[i] <- NA
  }
}
TAB3$ecart_relatif <- ecart_relatif
TAB3$ecart_relatif_pct <- round(ecart_relatif * 100, 1) 


# Result_global : ----
result_global <- TAB3 %>% 
  select(ATC3,l_atc3, nbc, age,nbc_total_FR, sexe, nb_attendu,somme_nb_attendu,SMR, BEN_REG,prevalence_brute, somme_prevalence_brute, G_NV_standardise_classe_age, G_NV_prevalence_totale, prevalence_brute_FR, ecart_relatif, ecart_relatif_pct) %>% 
  filter(BEN_REG == 75) 

# result_global2 <- TAB3 %>% 
#   select(ATC3,l_atc3, nbc, BEN_REG,age,sexe,nbc_total_FR, nb_attendu,somme_nb_attendu,SMR,prevalence_brute, somme_prevalence_brute) %>% 
#   filter(BEN_REG == 75) 
# View(result_global2)


# Tableau ATC3 ----

result_global_aggregated <- result_global %>%
  group_by(ATC3, l_atc3) %>%
  summarise(
    nbc_total = sum(nbc, na.rm = TRUE), 
    somme_prevalence_brute = mean(somme_prevalence_brute, na.rm = TRUE), 
    G_NV_prevalence_totale = mean(G_NV_prevalence_totale, na.rm = TRUE),  
    prevalence_brute_FR = mean(prevalence_brute_FR, na.rm = TRUE),  
    SMR = first(SMR),
    somme_nb_attendu = mean(somme_nb_attendu, na.rm = TRUE),
    ecart_relatif_pct = mean(ecart_relatif_pct, na.rm = TRUE),
    taux_hospitalisation_global = mean(ecart_relatif_pct, na.rm = TRUE),
    nbc_total_FR = first(nbc_total_FR),  
    .groups = "drop"
  ) %>%
  arrange(desc(ecart_relatif_pct)) %>%
  mutate(rang = row_number()) %>%
  select(rang, everything())
# IC NA ----
# Cette partie n'est pas utilisée : 
# Calculer les intervalles de confiance pour la Nouvelle-Aquitaine

# Fonction pour calculer les intervalles de confiance Poisson avec ajustement des bornes
# ic_poisson <- function(x, n, facteur = 100000, niveau_confiance = 0.95) {
#   # x : nombre de cas observés
#   # n : population (ou temps-personne)
#   # facteur : facteur de mise à l'échelle (par ex. pour 100000 personnes)
#   # niveau_confiance : niveau de confiance (par défaut 0.95)
#   
#   alpha <- 1 - niveau_confiance
#   
#   # Cas où x = 0 (aucun événement observé)
#   if (x == 0) {
#     lower <- 0
#     upper <- qchisq(1 - alpha / 2, 2 * (x + 1)) / 2
#   } else {
#     lower <- qchisq(alpha / 2, 2 * x) / 2
#     upper <- qchisq(1 - alpha / 2, 2 * (x + 1)) / 2
#   }
#   
#   # Calcul du taux et de ses bornes
#   taux <- (x / n) * facteur
#   ic_bas <- (lower / n) * facteur
#   ic_haut <- (upper / n) * facteur
#   
#   # Forcer la borne inférieure à 0 (pour ne pas avoir de négatif) et la borne supérieure à une valeur raisonnable
#   ic_bas <- max(ic_bas, 0)  # Ne pas avoir de bornes inférieures négatives
#   ic_haut <- min(ic_haut, 1000000)  # Plafonner la borne supérieure (valeur arbitraire pour éviter des intervalles trop larges)
#   
#   resultats <- data.frame(Cas = x, Population = n, Taux = taux, IC_basse = ic_bas, IC_haute = ic_haut)
#   return(resultats)
# }
#0.9 et 1.5

# Pour la loi de poisson : les intervalles de confiance les intervalles de confiances on étés calculés grâce à un programme annexe et ajouter manuellement dans les différentes cases du tableau 
result_global_aggregated$IC95_inf_manuel <- rep(NA, nrow(result_global_aggregated))
result_global_aggregated$IC95_sup_manuel <- rep(NA, nrow(result_global_aggregated))
indices_manuels <- c(1,2,3,5,6,9,10,13,18,39,44,95,100,104,108,112,114,122,125,127,133,137,138,145,147,149,155,162,168,172,175,176,177,179,181,182,183,184,185)
result_global_aggregated$IC95_inf_manuel[indices_manuels] <- c(3.9, 13.3, 0.3, 0.9, 27.1,14.9,8.9,0.3,26.83,53.7,3.12,13.3,45.7,78.5,3.4,46.1,12.1,5.9,62.2,5,11.2,62.9,30.6,27,6.65,71.3,69.1,82.4,1.1,52.2,41.3,0.5,1.76,57.2,29.4,1.4,40.8,9.0,3.0)
result_global_aggregated$IC95_sup_manuel[indices_manuels] <- c(4.8, 15.2, 0.7, 1.5,29.8,16.9,10.5,0.7,29.51,57.5,4.09,15.3,49.2,83.0,4.4,49.5,13.9,7.2,66.3,6.2,12.9,67,33.5,29.6,8,75.6,73.4,87.0,1.7,55.9,44.6,0.9,2.5,61.1,32.2,2.1,44.1,10.6,3.9)

# IC FR : 
result_global_aggregated$IC95F_inf_manuel2 <- rep(NA, nrow(result_global_aggregated))
result_global_aggregated$IC95F_sup_manuel2 <- rep(NA, nrow(result_global_aggregated))
indices_manuels2 <- c(1,2,3,5,6,9,10,13,18,44,108,114,122,127,133,147,168,176,177,182,184,185)
result_global_aggregated$IC95F_inf_manuel2[indices_manuels2] <- c(1.6,8.6,0.3,0.8,21.6,12.6,7.9,0.4,24.3,3.2,3.9,13.4,6.7,5.9,12.9,8.1,1.6,0.8,2.8,3.0,18.3,6.6)
result_global_aggregated$IC95F_sup_manuel2[indices_manuels2] <- c(1.8,9.0,0.4,0.9,22.3,13.2,8.3,0.5,25.1,3.5,4.2,14.0,7.1,6.2,13.5,8.5,1.7,1.0,3.1,3.3, 19.0,7.0)


# Initialisation des colonnes pour les IC
result_global_aggregated$IC95_inf <- NA
result_global_aggregated$IC95_sup <- NA


result_global_aggregated$IC95F_inf <- NA
result_global_aggregated$IC95F_sup <- NA

# Pour la Nouvelle-Aquitaine
for (i in 1:nrow(result_global_aggregated)) {
  prev_NA <- result_global_aggregated$G_NV_prevalence_totale[i]
  n_NA <- result_global_aggregated$nbc_total[i]
  
  if (!is.na(prev_NA) & !is.na(n_NA) & n_NA > 0 & prev_NA >= 0) {
    
    # Condition Poisson (petit effectif)
    if ((n_NA * prev_NA / 100000) < 5 & (n_NA * (1 - prev_NA) / 100000) < 5) {
      result_global_aggregated$IC95_inf[i] <- result_global_aggregated$IC95_inf_manuel[i]
      result_global_aggregated$IC95_sup[i] <- result_global_aggregated$IC95_sup_manuel[i]
      
    } else {
      # Sinon, calcul gaussien classique
      prev_prop <- prev_NA / 100000
      erreur <- 1.96 * sqrt(prev_prop * (1 - prev_prop) / n_NA)
      result_global_aggregated$IC95_inf[i] <- (prev_prop - erreur) * 100000
      result_global_aggregated$IC95_sup[i] <- (prev_prop + erreur) * 100000
    }
  }
}



### --- Pour la France entière ---

for (i in 1:nrow(result_global_aggregated)) {
  prev_FR <- result_global_aggregated$prevalence_brute_FR[i]
  n_FR <- result_global_aggregated$nbc_total_FR[i]
  
  if (i %in% indices_manuels2 ) {
    # Affectation forcée (exemple ici : NA, tu peux mettre ce que tu veux)
    result_global_aggregated$IC95F_inf[i] <- result_global_aggregated$IC95F_inf_manuel2[i]
    result_global_aggregated$IC95F_sup[i] <- result_global_aggregated$IC95F_sup_manuel2[i]
    
  } else {
    # Condition habituelle sur les données valides
    if (!is.na(prev_FR) & !is.na(n_FR) & n_FR > 0 & prev_FR >= 0) {
      prev_prop_FR <- prev_FR / 100000
      erreur_FR <- 1.96 * sqrt(prev_prop_FR * (1 - prev_prop_FR) / n_FR)
      result_global_aggregated$IC95F_inf[i] <- (prev_prop_FR - erreur_FR) * 100000
      result_global_aggregated$IC95F_sup[i] <- (prev_prop_FR + erreur_FR) * 100000
    } else {
      # Si données invalides, tu peux aussi forcer NA ou autre chose
      result_global_aggregated$IC95F_inf[i] <- NA
      result_global_aggregated$IC95F_sup[i] <- NA
    }
  }
}

# Formater les colonnes en texte [x : y]
result_global_aggregated$IC95 <- paste0(
  "[",
  round(result_global_aggregated$IC95_inf, 1),
  " ; ",
  round(result_global_aggregated$IC95_sup, 1),
  "]"
)

result_global_aggregated$IC95F <- paste0(
  "[",
  round(result_global_aggregated$IC95F_inf, 1),
  " ; ",
  round(result_global_aggregated$IC95F_sup, 1),
  "]"
)

result_global_aggregated$IC95_inf[1] <- "[ test]"

# Afficher le résultat
data1 <- result_global_aggregated



# Tableau2 ----
reactable(
  result_global_aggregated,
  columns = list(
    rang = colDef(name = "Rang", align = "center", width = 60, style = list(fontWeight = "bold")),
    ATC3 = colDef(name = "Code ATC3", headerStyle = list(textAlign = "center")),
    somme_prevalence_brute = colDef(name = "Prévalence brute ", format = colFormat(digits = 4)),
    G_NV_prevalence_totale = colDef(name = "Prévalence standardisée NA (‰)", format = colFormat(digits = 4)),
    nbc_total = colDef(name = "Effectif de consommation En Nouvelle Aquitaine", format = colFormat(separators = TRUE)),
    nbc_total_FR= colDef(name = "Effectif de consommation En France", format = colFormat(separators = TRUE)),
    prevalence_brute_FR = colDef(name = "Prévalence France (‰)", format = colFormat(digits = 4)),
    somme_nb_attendu = colDef(name = "Prévalence attendu", format = colFormat(digits = 2)), 
    ecart_relatif_pct = colDef(name = "Écart relatif (%)", format = colFormat(suffix = "%", digits = 3)),
    SMR = colDef(name = "ratio observé/attendu", format = colFormat(digits = 3)),
    taux_hospitalisation_global = colDef(name = "Écart relatif (%)", format = colFormat(suffix = "%", digits = 3)), 
    IC95 = colDef(name = "IC 95% NA", format = colFormat()),
    IC95F = colDef(name = "IC 95% France", format = colFormat())
  ),
  searchable = TRUE,
  sortable = TRUE,
  defaultPageSize = 10,
  striped = TRUE,
  highlight = TRUE,
  bordered = TRUE
)

# Hospitalisation: ----
# Data management ---- 
data2$Taux_hospit_st_NV <- as.numeric(data2$Taux_hospit_st_NV)
data2$Taux_hospit_FR <- as.numeric(data2$Taux_hospit_FR )
class(data2$Taux_hospit_FR )

# Ecart relatif: ----
# Créer une colonne pour l'écart relatif
data2$ecart_relatif_hospit <- NA

# Appliquer les calculs conditionnellement
for (i in 1:nrow(data2)) {
  # Vérifier si les valeurs nécessaires sont valides (non NA et non 0)
  if (is.na(data2$Taux_hospit_FR[i]) | is.na(data2$Taux_hospit_st_NV[i]) | data2$Taux_hospit_FR[i] == 0) {
    # Si non calculable, mettre "Non calculable"
    data2$ecart_relatif_hospit[i] <- "Non calculable"
  } else {
    # Sinon, faire le calcul et formater
    ecart <- (data2$Taux_hospit_st_NV[i] - data2$Taux_hospit_FR[i]) / data2$Taux_hospit_FR[i] * 100
    data2$ecart_relatif_hospit[i] <- paste0(round(ecart, 1), "%")
  }
}

#data2$ecart_relatif_hospit <- ecart_relatif_hospit

# Selection que des cases importantes : 
data2 <- data2 %>% 
  select(pathologie,taux_hospit_brute_NA,Nbr_hospit_NV,Nbr_hospit_FR, Taux_hospit_st_NV, Taux_hospit_FR,ecart_relatif_hospit)

# Tableau hospit ---- 
reactable(
  data2,
  columns = list(
    pathologie = colDef(name = "Rang", align = "center", width = 60, style = list(fontWeight = "bold")),
    Nbr_hospit_NV = colDef(name = "Nombre d'hospitalisation en Nouvelle Aquitaine", headerStyle = list(textAlign = "center")),
    Taux_hospit_st_NV = colDef(name = "Taux standardisé d'hospitalisation en Nouvelle Aquitaine", headerStyle = list(textAlign = "center")),
    Taux_hospit_FR = colDef(name = "Prévalence des hospitalisations en France", format = colFormat(digits = 2)),
    ecart_relatif_hospit= colDef(name = "Écart Relatif", format = colFormat(digits = 2), headerStyle = list(textAlign = "center"))
  ), 
  compact = TRUE,
  searchable = TRUE,
  sortable = TRUE,
  defaultPageSize = 10,
  striped = TRUE,
  highlight = TRUE,
  bordered = TRUE
)
# Visualisation ----

#UI
ui <- dashboardPage(
  dashboardHeader(title = "Projet"),
  dashboardSidebar(
    sidebarMenu(
      menuItem("Présentation", tabName = "presentation", icon = icon("info-circle")),
      menuItem("Méthode", tabName = "methode", icon = icon("info-circle")),
      menuItem("Analyse comparative ", tabName = "comparatif", icon = icon("chart-bar")),
      menuItem("Ratio", tabName = "ratio", icon = icon("balance-scale"))
      
    )
  ),
  dashboardBody(
    tabItems(
      # Onglet Présentation
      tabItem(tabName = "presentation",
              h2("Présentation de l'interface"),
              p(" La Nouvelle-Aquitaine est une région marquée par une population vieillissante et un profil épidémiologique diversifié.  "), 
              p("L’objectif principal de cette étude est d’évaluer les différences dans la consommation médicamenteuse entre la Nouvelle-Aquitaine et la France par classe thérapeutique (niveau 3 de la classification ATC). Cela permet de mieux comprendre les spécificités de consommation qui pourraient guider le pilotage sanitaire régional."),
              p("Le premier onglet présente une comparaison des taux de consommation standardisés selon l’âge et le sexe, entre la Nouvelle-Aquitaine et la France, par classes thérapeutique (niveau 3 de la classification ATC), accompagnée des écarts relatifs, du calcul du nombre de cas attendus et du SMR. A coté, se trouve les données de l’ATIH, en présentant les taux de recours aux établissements de soins de courte durée (MCO) ainsi que les principales causes d’hospitalisation."),
              p("Le deuxième onglet propose une mise en perspective du ratio consommation/hospitalisation en Nouvelle-Aquitaine et en France.")
      ),
      tabItem(tabName = "methode",
              h2("Méthode utilisée"),
              h4(" La base de données Open Medic du Système National des Données de Santé (SNDS)"), 
              p(" La base de données Open Medic recense les remboursements de médicaments délivrés en ville par l’ensemble des régimes d’assurance maladie, sur la période de 2014 à 2024. Ces données sont issues du SNDS. Le SNDS est la base médico-administrative nationale française, regroupant les données de remboursement des régimes d’assurance maladie obligatoires ainsi que celles provenant des établissements de santé. Il contient des informations pseudonymisées relatives aux soins, aux prescriptions remboursées en pharmacie de ville et aux pathologies, permettant l’analyse des parcours de soins et la mise en place de politiques de santé publique, tout en garantissant la confidentialité des patients et couvre plus de 99 % de la population française. L’accès à ces données individuelles pour motif d’évaluation ou de recherche à finalité de santé publique nécessite l’obtention d’autorisations règlementaires (ou l’appartenance à une institution bénéficiant d’un accès permanent ; le maniement de ces bases réclame en outre une expertise technique et des temps de traitement important.
Afin de rendre cette information plus facilement accessible et utilisable, différents jeux de données agrégés ont été mis à disposition de la communauté en ouvert, dont la base de données Open Medic – Open Medic fournit des informations exhaustives concernant les remboursements de médicaments effectués chaque année en France. Le codage des médicaments est effectué à l’aide de la classification ATC (Anatomique, Thérapeutique, Chimique) de l’Organisation Mondiale de la Santé.
L’information comprend le nombre d’utilisateurs annuels par sexe, classes d’âge et régions de résidences ; elle comprend également une information mensuelle sur le nombre de remboursements effectués (sans détails selon les caractéristiques d’âge et de sexe). Les deux informations renseignent également les montants remboursés annuellement par médicaments.
 "), 
              
              h4("La base de données : estimations de population par région, sexe et grande classe d’âge – Année 1975 à 2023, de l’Insee "), 
              p("L’Insee est l’organisme chargé de la collecte, du traitement et de la diffusion des données statistiques sur l’ensemble du territoire français. Il produit des estimations annuelles de la population des régions et des départements, en France métropolitaine et dans les départements d’outre-mer au 1er janvier.  Ces estimations sont disponibles sur la période 1975-2023 par sexe et grandes classes d’âges. Les estimations de population par sexe et âge sont des pyramides « par génération », obtenues à partir de l’année de naissance. Depuis 2021, le niveau de population et la pyramide des âges sont évalués annuellement à partir des statistiques d’état civil et d’une estimation du solde migratoire."),
              
              h4("La base de données : Morbidité hospitalière, de l’Agence technique de l’information sur l’hospitalisation"),
              p("L’ATIH a pour mission de collecter, traiter, analyser et diffuser les données issues des établissements de santé et médico-sociaux. Son objectif est de contribuer à l'amélioration de la qualité des soins et à la pertinence des prises en charge médicales. Elle produit également des indicateurs de santé, notamment à partir des séjours hospitaliers, permettant de décrire les pathologies traitées, les durées d’hospitalisation, les coûts et les niveaux de comorbidité. L’analyse porte spécifiquement sur la répartition des séjours en soins de courte durée MCO, selon le sexe, l’âge des patients et la pathologie traitée. Cela permet de mesurer et analyser la morbidité hospitalière. Elle représente une morbidité diagnostiquée, c’est-à-dire des affections identifiées et prises en charge par un professionnel de santé à l’occasion d’un contact avec le système hospitalier. Elle concerne en général des événements de santé suffisamment graves pour nécessiter une hospitalisation lors de leur survenue. Les diagnostics hospitaliers, qu’ils soient principaux ou associés, sont enregistrés à chaque séjour et codés selon la Classification Internationale des Maladies dans sa 10ᵉ révision (CIM-10), établie par l’Organisation mondiale de la santé (OMS). Les résultats présentés reposent sur le diagnostic principal, défini à la fin du séjour comme celui ayant nécessité l’essentiel de l’effort médical et soignant. L’analyse se concentre sur les séjours réalisés dans les services de médicine, chirurgie, obstétrique (MCO), aussi bien dans les établissements de santé publics que privés."),
              h4("Population d'étude"), 
              p("Parmi les 188 classes thérapeutiques de niveau ATC3 initialement présentes dans la base de données Open Medic, seules 184 ont été retenues pour l’analyse, les 4 restantes ne disposant d’aucune donnée exploitable (Vasodilatateur périphériques, les cicatrisants, les ocytociques, les anticestodes). En ce qui concerne les pathologies liées aux hospitalisations, seul le motif « toutes causes confondues » sera présenté dans les résultats. Toutefois, l’utilisateur a la possibilité de sélectionner une ou plusieurs pathologies parmi les 180 référencées dans la base de données de l’ATIH.
Dans le cadre de cette étude, ont été exclus les séjours de moins de 24 heures pour traitements en séances (chimiothérapies, radiothérapies), les nouveau-nés non hospitalisés, ainsi que les établissements non conventionnés et les structures dont l’activité principale ne relève pas du court séjour MCO. Par ailleurs, la base présente des défauts d’exhaustivité, notamment liés à l’absence ou à la sous-représentation de certains établissements publics sous dotation globale (< 100 lits MCO), ainsi que de certains établissements privés sous contrat dont l’activité est partiellement enregistrée. D’autre part, il est important de noter que l’unité de mesure est le séjour hospitalier et non le patient. Certains séjours sont exclus du champ de l’étude. Il s’agit notamment des nouveau-nés restés auprès de leur mère sans ouverture de dossier administratif, appelés « nouveau-nés non hospitalisés », des séjours de moins de 24 heures correspondant à des traitements réalisés en séances comme les chimiothérapies ou les radiothérapies, des unités MCO des hôpitaux locaux ou des établissements dont l’activité principale relève d’un autre champ que les soins de courte durée, comme la psychiatrie, les soins de suite ou la réadaptation, ainsi que des établissements à tarif d’autorité, également appelés « établissements non conventionnés ». Par ailleurs, il convient de souligner des défauts d’exhaustivités notamment par l’absence dans la base de données, des établissements sous dotation globale, tels que les hôpitaux publics et les établissements privés non lucratifs participant au service public hospitalier et ayant moins de 100 lits en MCO. De la même manière, certains établissements privés sous contrat avec les dont l’activité est seulement partiellement représentée dans la base PMSI, avec moins d’un séjour sur deux enregistré, voire aucune représentation ont étés exclus. 
"),
              h4("Données et variables utilisées"), 
              p("Les variables utilisées dans cette étude, extraites de la base Open Medic, portaient principalement sur plusieurs dimensions. La consommation médicamenteuse a été approchée par le nombre de patients consommateurs. L’analyse s’est appuyée sur le troisième niveau de la classification ATC permettant d’identifier le sous-groupe pharmacologique ou thérapeutique des médicaments en fonction du libellé ou du code ATC3. Sur des variables sociodémographiques telles que la région de résidence des bénéficiaires, leur âge et leur sexe. En effet, les femmes présentent une probabilité plus élevée d'avoir consommé des médicaments prescrits ou non au cours des dernières 24 heures (52,5 % contre 35,5 % pour les hommes). Cette différence peut s'expliquer par le fait qu'elles déclarent plus fréquemment des maladies et un état de santé perçu comme moins bon, ainsi que par leur tendance à consulter davantage les médecins, qu'il s'agisse de généralistes ou de spécialistes. De manière similaire, la consommation de médicaments augmente avec l'âge, accompagnée d'un risque accru de polymédication. Cette consommation est également fortement corrélée au nombre de maladies chroniques, dont la prévalence augmente avec l'âge. Raison pour lesquelles les données ont été standardisées en fonction du sexe et de l’âge."), 
              h4("Analyse statistique"), 
              p("L’ensemble des analyses et traitement de données ont étés réalisé à l’aide de Excel et R studio. La visualisation des données a été réalisée à l'aide du package shinydashboard pour la création de l'interface web.
Afin d’estimer la prévalence globale de consommation de manière comparable entre popula-tions, une standardisation directe par sexe et classe d’âge a été réalisée. L’objectif est de neu-traliser les effets liés aux différences de structure démographique entre les groupes étudiés.
Dans un premier temps, la prévalence brute par classe de médicaments est définie comme le rapport entre le nombre de consommateurs pour chaque classe de médicaments dans une classe d’âge et de sexe définie et la population totale correspondante à cette même classe d’âge et de sexe. Le taux de prévalence standardisé en Nouvelle-Aquitaine correspondant à la prévalence de la consommation médicamenteuse en Nouvelle-Aquitaine à proportion de chaque classe d’âges dans la population française totale. La prévalence globale standardisée est ensuite obtenue en faisant la somme des prévalences standardisées pour l’ensemble des groupes d’âges et sexe. Les intervalles de confiance au risque alpha de 5% ont étés calculés suivant l’approximation de la loi normale, sauf dans certains cas où les conditions d’application n’étaient pas remplies  ; une loi de Poisson a alors été utilisée.  
Dans la continuité de l’analyse, différents indicateurs ont étés construits : l’écart relatif a été calculé afin de mesurer la variation du taux de prévalence standardisé global par rapport à prévalence de consommation médicamenteuse en France. Il correspond à la différence entre le taux standardisé régional et le taux national, rapportée à ce dernier.
Une méthode de standardisation indirecte a été appliquée, en supposant que la population française avait la même structure démographique que celle de la Nouvelle-Aquitaine. Le taux d’utilisation de médicamenteuse par classes thérapeutique correspond à l’effectif d’utilisation médicamenteuse en France rapporté à la répartition de la population française par sexe et âge. Ce taux a ensuite été multiplié par la structure de sexe et d’âge de la Nouvelle-Aquitaine ce qui donne le nombre de cas attendu. Pour finir le standardized mortality ratio (SMR) cor-respond à la somme de médicaments en Nouvelle-Aquitaine rapporté aux effectifs attendu.  
Pour établir une correspondance entre la consommation de médicaments et la morbidité hospitalière, une base de données a été élaborée à partir des informations fournies par l'ATIH. Elle recense les causes d'hospitalisation par pathologies, les effectifs par séjours d’hospitalisation, les taux d'hospitalisation standardisés pour 1000 habitants, tant au niveau régional que national. Cette base permet dans un premier temps de visualiser les données relatives aux taux de morbidité en Nouvelle Aquitaine et en France puis de calculer un indice de comparaison pour la Nouvelle Aquitaine et la France correspondant à la prévalence de consommation médicamenteuse pour 100 000 patients par classe ATC3 rapporté au taux d’hospitalisation par pathologie également pour 100 000 patients.
")
      ),
      # Onglet 3 - Ratio
      tabItem(tabName = "ratio",
              h2("Analyse du ratio Consommation / Hospitalisation"),
              selectInput("classe_ratio", "Choisir une classe médicamenteuse :",
                          choices = c("Toutes", unique(data1$l_atc3))),
              selectInput("pathologie_ratio", "Choisir une pathologie :",
                          choices = c("Toutes", unique(data2$pathologie))),
              br(),
              # h4("Résultat du ratio :"),
              # textOutput("ratio_result"),
              # br(),
              actionButton("save_ratio", "Afficher les resultats"),
              actionButton("reset_ratios", "Réinitialiser les résultats", class = "btn-danger"),
              br(), br(),
              h4("Ratios enregistrés :"),
              reactableOutput("saved_ratios"),
              br()
      ),
      
      # Onglet 4 - Comparatif NA / France
      tabItem(tabName = "comparatif",
              h2("Analyse comparative régionale et nationale"),
              
              fluidRow(
                column(6,
                       selectizeInput("classe_comparatif", "Sélectionner une ou plusieurs classes médicamenteuses",
                                      choices = c("Toutes", unique(data1$l_atc3)),
                                      selected = "Toutes", multiple = TRUE)
                ),
                column(6,
                       selectizeInput("pathologie_comparatif", "Sélectionner une ou plusieurs pathologies",
                                      choices = c("Toutes", unique(data2$pathologie)),
                                      selected = "Toutes", multiple = TRUE)
                )
              ),
              br(),
              checkboxGroupInput("indicateurs_selection",
                                 "Choisir les indicateurs à afficher :",
                                 choices = c("Écart relatif (%)" = "ecart_relatif_pct",
                                             "Effectif Attendu" = "somme_nb_attendu",
                                             "SMR" = "SMR"),
                                 selected = c("ecart_relatif_pct", "somme_nb_attendu", "SMR")),
              br(),
              reactableOutput("tableau_classes_comparatif"),
              
              # Affichage côte à côte
              fluidRow(
                column(6,
                       h4("Comparaison des classes médicamenteuses "),
                       reactableOutput("tableau_classes_comparatif")
                ),
                column(6,
                       h4("Comparaison des hospitalisations "),
                       reactableOutput("tableau_hospit_comparatif"))
              )
      )
    )
  )  
)    


# serveur
server <- function(input, output) {
  # Filtrage des classes médicamenteuses
  # TABLEAU CLASSES COMPARATIF NA / FR
  data_filtrée_comparatif <- reactive({
    if (is.null(input$classe_comparatif) || "Toutes" %in% input$classe_comparatif) {
      data1
    } else {
      data1 %>% filter(l_atc3 %in% input$classe_comparatif)
    }
  })
  
  output$tableau_classes_comparatif <- renderReactable({
    #req(input$indicateurs_selection)
    
    colonnes_fixes <- c("ATC3", "l_atc3", 
                        "nbc_total", "G_NV_prevalence_totale", "IC95", 
                        "nbc_total_FR", "prevalence_brute_FR", "IC95F")
    
    colonnes_indicateurs <- input$indicateurs_selection
    colonnes_a_afficher <- c(colonnes_fixes, colonnes_indicateurs)
    
    # Ne conserver que les colonnes existantes dans les données
    colonnes_existantes <- intersect(colonnes_a_afficher, colnames(data_filtrée_comparatif()))
    
    df <- data_filtrée_comparatif()[, colonnes_existantes, drop = FALSE]
    
    # Colonnes reactable à définir dynamiquement
    coldefs <- list(
      ATC3 = colDef(name = "Code ATC3"),
      l_atc3 = colDef(name = "Libellé ATC3"),
      nbc_total = colDef(name = "Effectif", style = list(background = "#e6f0ff")),
      G_NV_prevalence_totale = colDef(name = "Prévalence standardisée pour 100 000 individus", format = colFormat(digits = 2), style = list(background = "#e6f0ff")),
      IC95 = colDef(name = "IC95", style = list(background = "#e6f0ff")),
      nbc_total_FR = colDef(name = "Effectif", style = list(background = "#ffe6e6")),
      prevalence_brute_FR = colDef(name = "Prévalence pour 100 000 individus", format = colFormat(digits = 2), style = list(background = "#ffe6e6")),
      IC95F = colDef(name = "IC95", style = list(background = "#ffe6e6")),
      ecart_relatif_pct = colDef(name = "Écart relatif (%)", format = colFormat(digits = 2)),
      somme_nb_attendu = colDef(name = "Effectif attendu", format = colFormat(digits = 0)),
      SMR = colDef(name = "SMR", format = colFormat(digits = 2))
    )
    
    # Détection dynamique des groupes de colonnes présents
    group_NA <- intersect(c("nbc_total", "G_NV_prevalence_totale", "IC95"), colnames(df))
    group_FR <- intersect(c("nbc_total_FR", "prevalence_brute_FR", "IC95F"), colnames(df))
    group_INDIC <- intersect(c("ecart_relatif_pct", "somme_nb_attendu", "SMR"), colnames(df))
    
    column_groups <- list()
    if (length(group_NA) > 0) {
      column_groups <- append(column_groups, list(colGroup(name = "Nouvelle-Aquitaine", columns = group_NA)))
    }
    if (length(group_FR) > 0) {
      column_groups <- append(column_groups, list(colGroup(name = "France", columns = group_FR)))
    }
    if (length(group_INDIC) > 0) {
      column_groups <- append(column_groups, list(colGroup(name = "Indicateurs", columns = group_INDIC)))
    }
    
    reactable(
      df,
      columns = coldefs[names(coldefs) %in% colnames(df)],
      columnGroups = column_groups,
      bordered = TRUE,
      striped = TRUE,
      highlight = TRUE,
      defaultPageSize = 10
    )
  })
  
  # Filtrage des hospitalisations
  data_filtrée_hospit <- reactive({
    if (is.null(input$pathologie_comparatif) || "Toutes" %in% input$pathologie_comparatif) {
      data2  # La base de données pour les hospitalisations
    } else {
      data2 %>% filter(pathologie %in% input$pathologie_comparatif)
    }
  }) 
  
  # TABLEAU HOSPIT COMPARATIF NA / FR
  output$tableau_hospit_comparatif <- renderReactable({
    reactable(
      data_filtrée_hospit() %>%
        select(pathologie, ecart_relatif_hospit, Nbr_hospit_NV, Taux_hospit_st_NV,  
               Nbr_hospit_FR, Taux_hospit_FR),
      style = list(tableLayout = "fixed"),
      
      columns = list(
        # Colonne commune
        pathologie = colDef(name = "Pathologie", style = list()),
        ecart_relatif_hospit = colDef(
          name = "Écart relatif (%)",
          cell = function(value) {
            if (is.na(value) || is.infinite(value) || value == 0) {
              "Non calculable"
            } else {
              sprintf("%s", value)
            }
          },
          style = function(value) {
            if (is.na(value) || is.infinite(value) || value == 0) {
              list(background = "#f0f0f0", color = "gray")  # Fond neutre pour les non calculables
            } else if (value > 0) {
              list(background = "#FFCCCC", color = "black")  # Rouge clair
            } else {
              list(background = "#CCFFCC", color = "black")  # Vert clair
            }
          }
        ),
        # Colonne pour la Nouvelle-Aquitaine avec couleur de fond
        Nbr_hospit_NV = colDef(
          name = "Effectif", 
          format = colFormat(digits = 0),
          style = list(background = "#e6f0ff", Width = 40)  
        ),
        Taux_hospit_st_NV = colDef(
          name = "Taux hospit", 
          format = colFormat(digits = 2),
          style = list(background = "#e6f0ff")  # Couleur de fond pour Nouvelle-Aquitaine
        ),
        
        # Colonne pour la France avec couleur de fond différente
        Nbr_hospit_FR = colDef(
          name = "Effectif", 
          format = colFormat(digits = 0),
          style = list(background = "#ffe6e6")  # Couleur de fond pour France
        ),
        Taux_hospit_FR = colDef(
          name = "Taux hospit", 
          format = colFormat(digits = 2),
          style = list(background = "#ffe6e6")  # Couleur de fond pour France
        )
      ),
      
      columnGroups = list(
        # Groupes pour Nouvelle-Aquitaine et France
        colGroup(name = "Nouvelle-Aquitaine", columns = c("Nbr_hospit_NV", "Taux_hospit_st_NV")),
        colGroup(name = "France", columns = c("Nbr_hospit_FR", "Taux_hospit_FR"))
      ),
      
      bordered = TRUE,
      highlight = TRUE,
      striped = TRUE,
      defaultPageSize = 10
    )
  })
  
  
  # Onglet 3 - Ratio conso/hospit
  
  # Initialiser la variable réactive pour stocker les données sauvegardées
  saved_data <- reactiveVal(data.frame(
    Classe = character(),
    Pathologie = character(),
    Ratio = character(),     # Utilise character ici pour permettre "Non calculable"
    Ratio_FR = character(), 
    stringsAsFactors = FALSE
  ))
  
  observeEvent(input$save_ratio, {
    conso <- if (input$classe_ratio == "Toutes") {
      mean(data1$G_NV_prevalence_totale, na.rm = TRUE)
    } else {
      mean(filter(data1, l_atc3 == input$classe_ratio)$G_NV_prevalence_totale, na.rm = TRUE)
    }
    
    hospit <- if (input$pathologie_ratio == "Toutes") {
      mean(data2$Taux_hospit_st_NV, na.rm = TRUE)
    } else {
      mean(filter(data2, pathologie == input$pathologie_ratio)$Taux_hospit_st_NV, na.rm = TRUE)
    }
    
    # Calcul du ratio France
    conso_FR <- if (input$classe_ratio == "Toutes") {
      mean(data1$prevalence_brute_FR, na.rm = TRUE)
    } else {
      mean(filter(data1, l_atc3 == input$classe_ratio)$prevalence_brute_FR, na.rm = TRUE)
    }
    
    hospit_FR <- if (input$pathologie_ratio == "Toutes") {
      mean(data2$Taux_hospit_FR, na.rm = TRUE)
    } else {
      mean(filter(data2, pathologie == input$pathologie_ratio)$Taux_hospit_FR, na.rm = TRUE)
    }
    
    
    # Vérification et calculs
    # Ratio France & NA
    ratio <- if (!is.na(hospit) && hospit != 0) round(conso / hospit, 2) else "Non calculable"
    ratio_FR <- if (!is.na(hospit_FR) && hospit_FR != 0) round(conso_FR / hospit_FR, 2) else "Non calculable"
    
    # Création de la ligne à ajouter
    new_entry <- data.frame(
      Classe = input$classe_ratio,
      Pathologie = input$pathologie_ratio,
      Ratio = ratio,
      Ratio_FR = ratio_FR,
      stringsAsFactors = FALSE
    )
    
    # Ajout dans la variable réactive
    saved_data(rbind(saved_data(), new_entry))
  })
  
  
  # Réinitialisation des données sauvegardées
  observeEvent(input$reset_ratios, {
    saved_data(data.frame(
      Classe = character(),
      Pathologie = character(),
      Ratio = numeric(),
      Ratio_FR = numeric(),  
      stringsAsFactors = FALSE
    ))
  })
  
  # Affichage
  output$saved_ratios <- renderReactable({
    reactable(
      saved_data(),
      bordered = TRUE,
      striped = TRUE,
      highlight = TRUE,
      sortable = TRUE,
      defaultPageSize = 10,
      columns = list(
        Classe = colDef(name = "Classe Médicamenteuse", minWidth = 150),
        Pathologie = colDef(name = "Pathologie", minWidth = 150),
        
        Ratio = colDef(
          name = "Nouvelle-Aquitaine",
          format = colFormat(digits = 2),
          style = function(value, index) {
            if (is.na(value) || value == "Non calculable") return()
            ratio_FR <- saved_data()[index, "Ratio_FR"]
            if (value >= ratio_FR) {
              list(background = "#f8d7da", color = "#721c24", fontWeight = "bold")
            } else {
              list(background = "#d4edda", color = "#155724", fontWeight = "bold")
            }
          }
        ),
        
        Ratio_FR = colDef(
          name = "France",
          format = colFormat(digits = 2),
          style = function(value, index) {
            if (is.na(value) || value == "Non calculable") return()
            ratio_NV <- saved_data()[index, "Ratio"]
            if (value >= ratio_NV) {
              list(background = "#f8d7da", color = "#721c24", fontWeight = "bold")
            } else {
              list(background = "#d4edda", color = "#155724", fontWeight = "bold")
            }
          }
        )
      )
    )
  })
  
}

# ---- Run App ----
shinyApp(ui, server)

Ce script à servi pour calculer les inveralles de confiance suivant la loi de poisson

library(epitools)
ic_poisson_exact <- function(prevalence, n, facteur = 100000, niveau_confiance = 0.95) {
  # Calcul de l'intervalle de confiance exact avec la loi de Poisson
  # Calcul du nombre d'événements en fonction de la prévalence et de la population
  x <- round(prevalence * n / facteur)
  
  # Calcul de l'intervalle de confiance exact pour la loi de Poisson
  ic <- pois.exact(x, pt = n, conf.level = niveau_confiance)
  
  # Taux pour 100 000 habitants
  taux <- ic$rate * facteur
  ic_bas <- ic$lower * facteur
  ic_haut <- ic$upper * facteur
  
  # Forcer la borne inférieure à 0, borne supérieure plafonnée si souhaité
  ic_bas <- max(ic_bas, 0)
  ic_haut <- min(ic_haut, 1000000)  # Plafond arbitraire
  
  resultats <- data.frame(Prevalence = prevalence, Population = n, Taux = taux, IC_basse = ic_bas, IC_haute = ic_haut)
  return(resultats)
}
# A changer pour chaque classes thérapeutiques 
prevalence <- 6.84# Prévalence pour 100 000 habitants
n <- 65834837 # Taille de la population

# Calcul de l'intervalle de confiance
resultat_ic <- ic_poisson_exact(prevalence, n)
print(resultat_ic)