Affecter couleur standard selon itération de for pour graphique ggplot

Postez ici vos questions, réponses, commentaires ou suggestions - Les sujets seront ultérieurement répartis dans les archives par les modérateurs

Modérateur : Groupe des modérateurs

Samuel Pereira Dias
Messages : 62
Enregistré le : 07 Mar 2014, 11:09

Affecter couleur standard selon itération de for pour graphique ggplot

Messagepar Samuel Pereira Dias » 16 Aoû 2022, 16:35

Bonjour,

A l'occasion de la création de graphique avec ggplot, J'essaie d'affecter une couleur unique à un type qui sera sélectionné selon l'itération d'une boucle.

Le Df :

Code : Tout sélectionner

structure(list(Unité = c("Autres", "Autres", "Autres", "Autres",
"Autres", "Autres", "Autres", "Autres", "Autres", "Autres", "Autres",
"Autres", "Autres", "Autres", "Autres", "Autres", "Autres", "Autres",
"Autres", "Autres", "Autres", "Autres", "Autres", "Autres", "Autres",
"Autres", "Autres", "Autres", "Autres", "Autres"), Catégorie.de.l.animal = c("Poissons",
"Insecte, crustacés d'eau douce", "Poissons", "Poissons", "Poissons",
"Viande sauvage", "Poissons", "Poissons", "Poissons", "Poissons",
"Poissons", "Poissons", "Poissons", "Viande sauvage", "Poissons",
"Poissons", "Poissons", "Poissons", "Viande sauvage", "Poissons",
"Poissons", "Poissons", "Poissons", "Viande sauvage", "Viande sauvage",
"Viande sauvage", "Viande sauvage", "Poissons", "Viande sauvage",
"Viande sauvage"), Condition = c("Fumé", "Fumé", "Fumé", "Fumé",
"Fumé", "Frais", "Fumé", "Fumé", "Fumé", "Fumé", "Fumé",
"Fumé", "Fumé", "Fumé", "Fumé", "Vivant", "Fumé", "Vivant",
"Fumé", "Fumé", "Frais", "Frais", "Fumé", "Frais", "Frais",
"Fumé", "Fumé", "Salé", "Fumé", "Frais"), Prix.d.une.unité = c(25000L,
100L, 10000L, 10000L, 40000L, 500L, 15000L, 2000L, 1000L, 2000L,
1000L, 500L, 5000L, 500L, 35000L, 28000L, 2000L, 30000L, 500L,
3000L, 500L, 500L, 5000L, 500L, 500L, 500L, 250L, 2500L, 250L,
500L)), row.names = c(NA, 30L), class = "data.frame")


Les couleurs selon la modalité :

Code : Tout sélectionner

col=c("#00B479","#69BDDD", "#E37C3E","#FCC524","#7f00ff", "#3399ff","#000000")
col2<-c("Entier","Moitié","Pile","Pièce","Kg","Quartier","Autres")
colB<-cbind(col,col2)


Et le code résumant le df + cherchant la création du graphique via ggplot

Code : Tout sélectionner

for (i in unique(sale$Catégorie.de.l.animal)) {
  sub<-subset(sale, Catégorie.de.l.animal == i ) # je créé un sub à chaque itération du i
 
  res<-aggregate(list(prixMean=sub$Prix.d.une.unité),
                 list(condition=sub$Condition, unité=sub$Unité),
                 mean, na.rm=T) # J'effectue mon résumé statistique voulu
 
  res$unité <- with(res, reorder(unité,-prixMean)) # que je réordonne en décroissant
  res<-merge(res,colB, by.x="unité", by.y="col2", all.X=T) # je join les couleurs dans le df qui sera plotté
 
  x11()
  p<-ggplot(res, aes(unité, prixMean, fill=condition)) +
  geom_bar(stat="identity",position=position_dodge(0.5),width = 0.7) +
    scale_fill_discrete(res$col) + ## Fonction ne fonctionnant pas
    xlab("Type d'unité") +
    ylab("Prix moyen par type d'unité") +
    theme(axis.title.x = element_text(color="red", size=20, face="bold")) +
  ggtitle(i)+
  theme_classic()
  print(p)
  }


Je n'arrive pas à rendre standard la sélection de la couleur avec la sélection du facteur unité. Elles alternent selon les "unités" sélectionnées dans le sub (logique). J'aimerai par exemple que "fumé" soit rouge, "frais" soit bleu, etc.. sur les 5 graphiques produits.

Il me manque juste la petite logique (ou fonction) ggplot pour lui passer la bonne commande, mais laquelle ?

D'avance merci pour votre aide,
Cordialement,
Samuel
Samuel Pereira Dias

Mickael Canouil
Messages : 1315
Enregistré le : 04 Avr 2011, 08:53
Contact :

Re: Affecter couleur standard selon itération de for pour graphique ggplot

Messagepar Mickael Canouil » 16 Aoû 2022, 20:49

A part qu'il manque des bouts pour que ce soit vraiment reproductible est que les specifications du graphique semblent erronées (par exemple vous voulez une seule couleur pour plusieurs conditions différentes ...), voici une version fonctionnelle du code en conservant les bizarreries graphiques du votre :

Code : Tout sélectionner

sale <- structure(list(Unité = c(
  "Autres", "Autres", "Autres", "Autres",
  "Autres", "Autres", "Autres", "Autres", "Autres", "Autres", "Autres",
  "Autres", "Autres", "Autres", "Autres", "Autres", "Autres", "Autres",
  "Autres", "Autres", "Autres", "Autres", "Autres", "Autres", "Autres",
  "Autres", "Autres", "Autres", "Autres", "Autres"
), Catégorie.de.l.animal = c(
  "Poissons",
  "Insecte, crustacés d'eau douce", "Poissons", "Poissons", "Poissons",
  "Viande sauvage", "Poissons", "Poissons", "Poissons", "Poissons",
  "Poissons", "Poissons", "Poissons", "Viande sauvage", "Poissons",
  "Poissons", "Poissons", "Poissons", "Viande sauvage", "Poissons",
  "Poissons", "Poissons", "Poissons", "Viande sauvage", "Viande sauvage",
  "Viande sauvage", "Viande sauvage", "Poissons", "Viande sauvage",
  "Viande sauvage"
), Condition = c(
  "Fumé", "Fumé", "Fumé", "Fumé",
  "Fumé", "Frais", "Fumé", "Fumé", "Fumé", "Fumé", "Fumé",
  "Fumé", "Fumé", "Fumé", "Fumé", "Vivant", "Fumé", "Vivant",
  "Fumé", "Fumé", "Frais", "Frais", "Fumé", "Frais", "Frais",
  "Fumé", "Fumé", "Salé", "Fumé", "Frais"
), Prix.d.une.unité = c(
  25000L,
  100L, 10000L, 10000L, 40000L, 500L, 15000L, 2000L, 1000L, 2000L,
  1000L, 500L, 5000L, 500L, 35000L, 28000L, 2000L, 30000L, 500L,
  3000L, 500L, 500L, 5000L, 500L, 500L, 500L, 250L, 2500L, 250L,
  500L
)), row.names = c(NA, 30L), class = "data.frame")

colB <- data.frame(
  Unité = c("Entier", "Moitié", "Pile", "Pièce", "Kg", "Quartier", "Autres"),
  colour = c("#00B479", "#69BDDD", "#E37C3E", "#FCC524", "#7f00ff", "#3399ff", "#000000")
)

library(ggplot2)

plot_list <- lapply(
  X = sort(unique(sale[["Catégorie.de.l.animal"]])),
  data = sale,
  FUN = function(i, data) {
    res <- merge(
      x = aggregate(
        x = Prix.d.une.unité ~ Unité + Condition,
        data = subset(data, Catégorie.de.l.animal == i),
        FUN = mean,
        na.rm = TRUE
      
),
      y = colB,
      by = "Unité",
      all.= TRUE
    
)
    res[["Unité"]] <- with(res, reorder(Unité, -Prix.d.une.unité))

    p <- ggplot(res) +
      aes(= Unité, y = Prix.d.une.unité, group = Condition, fill = colour) +
      geom_col(position = position_dodge(0.9)) +
      scale_fill_identity() +
      scale_y_continuous(expand = expansion(c(0, 0.1))) +
      labs(
        x = "Type d'unité",
        y = "Prix moyen par type d'unité",
        title = i
      
) +
      theme_classic() +
      theme(axis.title.= element_text(color = "red", size = 20, face = "bold"))
  }
)

library(patchwork)
wrap_plots(plot_list


Image
Mickaël
mickael.canouil.fr | rlille.fr

Samuel Pereira Dias
Messages : 62
Enregistré le : 07 Mar 2014, 11:09

Re: Affecter couleur standard selon itération de for pour graphique ggplot

Messagepar Samuel Pereira Dias » 17 Aoû 2022, 09:08

Bonjour Mickaël,

Merci cela fonctionne bien. Effectivement, il y avait quelques incohérences sur ma demande. Les couleurs étaient pour le champ "Condition" et non pas "unité" comme je l'avais demandé. J'ai donc corrigé cela sur votre code, et ça parait bien correspondre à mes besoins. Toutefois, je n'arrive pas à afficher la légende, et ne vois pas de commande de suppression de légende dans le code. Cela est-il dû à l'utilisation du wrap_plots ?


Je joins ici un dput que j'espère avoir amélioré, ainsi que le code corrigé :

Code : Tout sélectionner


sale<-structure(list(Unité = c("Entier", "Entier", "Autres", "Pile",
"Pile", "Pièce", "Autres", "Autres", "Pile", "Pile", "Pile",
"Pile", "Autres", "Pile", "Autres", "Autres", "Pile", "Autres",
"Autres", "Entier", "Pile", "Entier", "Pile", "Pile", "Entier",
"Pile", "Pile", "Pile", "Pile", "Pile"),
Catégorie.de.l.animal = c("Poissons",
"Viande domestique", "Poissons", "Viande sauvage", "Viande sauvage",
"Viande sauvage", "Poissons", "Poissons", "Viande domestique",
"Poissons", "Poissons", "Poissons", "Poissons", "Poissons", "Poissons",
"Viande sauvage", "Viande domestique", "Poissons", "Insecte, crustacés d'eau douce",
"Viande sauvage", "Poissons", "Viande sauvage", "Poissons", "Poissons",
"Viande sauvage", "Poissons", "Viande sauvage", "Viande sauvage",
"Viande sauvage", "Poissons"),
Condition = c("Salé", "Congelé",
"Fumé", "Fresh", "Fresh", "Fumé", "Fumé", "Fumé", "Congelé",
"Fumé", "Fumé", "Fumé", "Fumé", "Salé", "Fumé", "Fumé",
"Congelé", "Fumé", "Fumé", "Fumé", "Fumé", "Fresh", "Fumé",
"Fumé", "Fumé", "Fumé", "Fumé", "Fresh", "Fresh", "Fumé"
),
Prix.d.une.unité = c(5000L, 1300L, 10000L, 500L, 500L, 5000L,
75000L, 5000L, 500L, 5000L, 5000L, 10000L, 4000L, 500L, 1500L,
250L, 500L, 1000L, 100L, 3500L, 10000L, 7500L, 1000L, 20000L,
5500L, 5000L, 500L, 500L, 2000L, 1500L)), row.names = c(3159L,
4417L, 2537L, 8461L, 9425L, 5229L, 2144L, 296L, 6786L, 5577L,
10572L, 6407L, 2626L, 7794L, 2283L, 871L, 10450L, 2584L, 610L,
4301L, 8701L, 3922L, 6481L, 10938L, 3633L, 7302L, 7635L, 7364L,
5928L, 10198L), class = "data.frame")




Code : Tout sélectionner

colB <- data.frame(
  Condition =c("Fumé","Fresh","Vivant","Salé","Congelé"),
  colour = c("#00B479","#69BDDD", "#E37C3E","#FCC524","#7f00ff")
)

plot_list <- lapply(
  X = sort(unique(sale[["Catégorie.de.l.animal"]])),
  data = sale,
  FUN = function(i, data) {
    res <- merge(
      x = aggregate(
        x = Prix.d.une.unité ~ Unité + Condition,
        data = subset(data, Catégorie.de.l.animal == i),
        FUN = mean,
        na.rm = TRUE
      ),
      y = colB,
      by = "Condition",
      all.x = TRUE
    )
   
    res[["Unité"]] <- with(res, reorder(Unité, -Prix.d.une.unité))
   
    p <- ggplot(res) +
      aes(x = Unité, y = Prix.d.une.unité, group = Condition, fill = colour) +
      geom_col(position = position_dodge(0.9)) +
      scale_fill_identity() +
      scale_y_continuous(expand = expansion(c(0, 0.1))) +
      labs(
        x = "Type d'unité",
        y = "Prix moyen par type d'unité",
        title = i
      ) +
      theme_classic() +
      theme(legend.background = element_rect(fill="lightblue",
                                             size=0.5, linetype="solid"),
            legend.position = c(0.5, 0.5))+
      theme(axis.title.x = element_text(size = 12))
  }
)

# library(patchwork)
X11()
wrap_plots(plot_list)


Merci de votre aide,
Samuel
Samuel Pereira Dias

Mickael Canouil
Messages : 1315
Enregistré le : 04 Avr 2011, 08:53
Contact :

Re: Affecter couleur standard selon itération de for pour graphique ggplot

Messagepar Mickael Canouil » 17 Aoû 2022, 11:45

Pour que le code soit fonctionnel, il faut laisser les extensions R.

Comme la demande initiale n'est pas en fait pas la bonne, voici le code qui correspond à ce que vous voulez semble-t-il faire.

Code : Tout sélectionner

library(patchwork)
library(ggplot2)
#> Warning: package 'ggplot2' was built under R version 4.2.1

sale <- structure(list(
  Unité = c(
    "Entier", "Entier", "Autres", "Pile",
    "Pile", "Pièce", "Autres", "Autres", "Pile", "Pile", "Pile",
    "Pile", "Autres", "Pile", "Autres", "Autres", "Pile", "Autres",
    "Autres", "Entier", "Pile", "Entier", "Pile", "Pile", "Entier",
    "Pile", "Pile", "Pile", "Pile", "Pile"
  ),
  Catégorie.de.l.animal = c(
    "Poissons",
    "Viande domestique", "Poissons", "Viande sauvage", "Viande sauvage",
    "Viande sauvage", "Poissons", "Poissons", "Viande domestique",
    "Poissons", "Poissons", "Poissons", "Poissons", "Poissons", "Poissons",
    "Viande sauvage", "Viande domestique", "Poissons", "Insecte, crustacés d'eau douce",
    "Viande sauvage", "Poissons", "Viande sauvage", "Poissons", "Poissons",
    "Viande sauvage", "Poissons", "Viande sauvage", "Viande sauvage",
    "Viande sauvage", "Poissons"
  ),
  Condition = c(
    "Salé", "Congelé",
    "Fumé", "Fresh", "Fresh", "Fumé", "Fumé", "Fumé", "Congelé",
    "Fumé", "Fumé", "Fumé", "Fumé", "Salé", "Fumé", "Fumé",
    "Congelé", "Fumé", "Fumé", "Fumé", "Fumé", "Fresh", "Fumé",
    "Fumé", "Fumé", "Fumé", "Fumé", "Fresh", "Fresh", "Fumé"
  ),
  Prix.d.une.unité = c(
    5000L, 1300L, 10000L, 500L, 500L, 5000L,
    75000L, 5000L, 500L, 5000L, 5000L, 10000L, 4000L, 500L, 1500L,
    250L, 500L, 1000L, 100L, 3500L, 10000L, 7500L, 1000L, 20000L,
    5500L, 5000L, 500L, 500L, 2000L, 1500L
  )
), row.names = c(
  3159L,
  4417L, 2537L, 8461L, 9425L, 5229L, 2144L, 296L, 6786L, 5577L,
  10572L, 6407L, 2626L, 7794L, 2283L, 871L, 10450L, 2584L, 610L,
  4301L, 8701L, 3922L, 6481L, 10938L, 3633L, 7302L, 7635L, 7364L,
  5928L, 10198L
), class = "data.frame")

colour_scale <- c(
  "Fumé" = "#00B479",
  "Fresh" = "#69BDDD",
  "Vivant" = "#E37C3E",
  "Salé" = "#FCC524",
  "Congelé" = "#7f00ff"
)

plot_list <- lapply(
  X = sort(unique(sale[["Catégorie.de.l.animal"]])),
  data = sale,
  FUN = function(i, data) {
    res <- aggregate(
      x = Prix.d.une.unité ~ Unité + Condition,
      data = subset(data, Catégorie.de.l.animal == i),
      FUN = mean,
      na.rm = TRUE
    )
    res[["Unité"]] <- with(res, reorder(Unité, -Prix.d.une.unité))

    p <- ggplot(res) +
      aes(x = Unité, y = Prix.d.une.unité, fill = Condition) +
      geom_col(position = position_dodge(0.9)) +
      scale_fill_manual(values = colour_scale) +
      scale_y_continuous(expand = expansion(c(0, 0.1))) +
      labs(
        x = "Type d'unité",
        y = "Prix moyen par type d'unité",
        title = i
      ) +
      theme_classic() +
      theme(
        legend.background = element_rect(
          fill = "lightblue",
          size = 0.5,
          linetype = "solid"
        ),
        legend.position = c(0.5, 0.5)
      ) +
      theme(axis.title.x = element_text(size = 12))
  }
)

wrap_plots(plot_list, guides = "collect")


Image
Mickaël
mickael.canouil.fr | rlille.fr

Samuel Pereira Dias
Messages : 62
Enregistré le : 07 Mar 2014, 11:09

Re: Affecter couleur standard selon itération de for pour graphique ggplot

Messagepar Samuel Pereira Dias » 22 Aoû 2022, 13:05

Bonjour Mickaël, cela marche parfaitement bien. J'ai pu repartir de ce code pour développer de nombreuses autres modèles graphiques.
Merci !
Samuel
Samuel Pereira Dias


Retourner vers « Questions en cours »

Qui est en ligne

Utilisateurs parcourant ce forum : Google [Bot] et 1 invité