web-dev-qa-db-fra.com

Comment assigner des couleurs aux variables catégorielles dans ggplot2 qui ont un mapping stable?

Je me suis familiarisé avec R au cours du dernier mois.

Voici ma question:

Quel est un bon moyen d'attribuer des couleurs aux variables catégoriques dans ggplot2 qui ont un mapping stable? J'ai besoin de couleurs cohérentes sur un ensemble de graphiques comportant différents sous-ensembles et un nombre différent de variables catégorielles.

Par exemple,

plot1 <- ggplot(data, aes(xData, yData,color=categoricaldData)) + geom_line()

categoricalData a 5 niveaux.

Puis

plot2 <- ggplot(data.subset, aes(xData.subset, yData.subset, 
                                 color=categoricaldData.subset)) + geom_line()

categoricalData.subset a 3 niveaux.

Cependant, un niveau particulier qui se trouve dans les deux ensembles se retrouvera avec une couleur différente, ce qui rend plus difficile la lecture simultanée des graphiques.

Dois-je créer un vecteur de couleurs dans le bloc de données? Ou existe-t-il un autre moyen d'attribuer des couleurs spécifiques à des catégories?

155
wintour

Pour des situations simples comme l'exemple exact du PO, je conviens que la réponse de Thierry est la meilleure. Cependant, je pense qu'il est utile de souligner une autre approche qui devient plus facile lorsque vous essayez de maintenir des schémas de couleurs cohérents sur plusieurs trames de données qui sont non toutes obtenues en sous-configurant un seul grand cadre de données. La gestion des niveaux de facteurs dans plusieurs blocs de données peut devenir fastidieuse si ceux-ci sont extraits de fichiers distincts et si tous les niveaux de facteurs n'apparaissent pas dans chaque fichier.

Une façon de résoudre ce problème consiste à créer une échelle de couleurs manuelle personnalisée, comme suit:

#Some test data
dat <- data.frame(x=runif(10),y=runif(10),
        grp = rep(LETTERS[1:5],each = 2),stringsAsFactors = TRUE)

#Create a custom color scale
library(RColorBrewer)
myColors <- brewer.pal(5,"Set1")
names(myColors) <- levels(dat$grp)
colScale <- scale_colour_manual(name = "grp",values = myColors)

puis ajoutez l’échelle de couleur sur la parcelle au besoin:

#One plot with all the data
p <- ggplot(dat,aes(x,y,colour = grp)) + geom_point()
p1 <- p + colScale

#A second plot with only four of the levels
p2 <- p %+% droplevels(subset(dat[4:10,])) + colScale

La première parcelle ressemble à ceci:

enter image description here

et la deuxième parcelle ressemble à ceci:

enter image description here

De cette façon, vous n'avez pas besoin de vous souvenir ou de vérifier chaque trame de données pour voir qu'ils ont les niveaux appropriés.

164
joran

Je suis dans la même situation que celle indiquée par malcook dans son commentaire : malheureusement le réponse par Thierry ne fonctionne pas avec ggplot2 version 0.9.3.1.

png("figure_%d.png")
set.seed(2014)
library(ggplot2)
dataset <- data.frame(category = rep(LETTERS[1:5], 100),
    x = rnorm(500, mean = rep(1:5, 100)),
    y = rnorm(500, mean = rep(1:5, 100)))
dataset$fCategory <- factor(dataset$category)
subdata <- subset(dataset, category %in% c("A", "D", "E"))

ggplot(dataset, aes(x = x, y = y, colour = fCategory)) + geom_point()
ggplot(subdata, aes(x = x, y = y, colour = fCategory)) + geom_point()

Ici c'est le premier chiffre:

ggplot A-E, mixed colors

et la deuxième figure:

ggplot ADE, mixed colors

Comme on peut le constater, les couleurs ne restent pas fixes. Par exemple, E passe de Magenta à Bleu.

Comme suggéré par malcook dans son commentaire et par hadley dans son commentaire le code qui utilise limits fonctionne correctement:

ggplot(subdata, aes(x = x, y = y, colour = fCategory)) +       
    geom_point() + 
    scale_colour_discrete(drop=TRUE,
        limits = levels(dataset$fCategory))

donne le chiffre suivant, qui est correct:

correct ggplot

Voici le résultat de sessionInfo():

R version 3.0.2 (2013-09-25)
Platform: x86_64-pc-linux-gnu (64-bit)

locale:
 [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C              
 [3] LC_TIME=en_US.UTF-8        LC_COLLATE=en_US.UTF-8    
 [5] LC_MONETARY=en_US.UTF-8    LC_MESSAGES=en_US.UTF-8   
 [7] LC_PAPER=en_US.UTF-8       LC_NAME=C                 
 [9] LC_ADDRESS=C               LC_TELEPHONE=C            
[11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C       

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

other attached packages:
[1] ggplot2_0.9.3.1

loaded via a namespace (and not attached):
 [1] colorspace_1.2-4   dichromat_2.0-0    digest_0.6.4       grid_3.0.2        
 [5] gtable_0.1.2       labeling_0.2       MASS_7.3-29        munsell_0.4.2     
 [9] plyr_1.8           proto_0.3-10       RColorBrewer_1.0-5 reshape2_1.2.2    
[13] scales_0.2.3       stringr_0.6.2 
38
Alessandro Jacopson

La solution la plus simple consiste à convertir votre variable catégorielle en un facteur antérieur au sous-ensemble. En bout de ligne, vous avez besoin d’une variable de facteur avec exactement les mêmes niveaux dans tous vos sous-ensembles.

library(ggplot2)
dataset <- data.frame(category = rep(LETTERS[1:5], 100), 
    x = rnorm(500, mean = rep(1:5, 100)), y = rnorm(500, mean = rep(1:5, 100)))
dataset$fCategory <- factor(dataset$category)
subdata <- subset(dataset, category %in% c("A", "D", "E"))

Avec une variable de caractère

ggplot(dataset, aes(x = x, y = y, colour = category)) + geom_point()
ggplot(subdata, aes(x = x, y = y, colour = category)) + geom_point()

Avec une variable facteur

ggplot(dataset, aes(x = x, y = y, colour = fCategory)) + geom_point()
ggplot(subdata, aes(x = x, y = y, colour = fCategory)) + geom_point()
20
Thierry

Sur la base de la réponse très utile de Joran, j'ai pu proposer cette solution pour une échelle de couleurs stable pour un facteur booléen (TRUE, FALSE).

boolColors <- as.character(c("TRUE"="#5aae61", "FALSE"="#7b3294"))
boolScale <- scale_colour_manual(name="myboolean", values=boolColors)

ggplot(myDataFrame, aes(date, duration)) + 
  geom_point(aes(colour = myboolean)) +
  boolScale

Etant donné que ColorBrewer n’est pas très utile avec les échelles de couleurs binaires, les deux couleurs nécessaires sont définies manuellement.

Ici, myboolean est le nom de la colonne dans myDataFrame contenant le facteur TRUE/FALSE. date et duration sont les noms de colonne à mapper sur les axes x et y du tracé dans cet exemple.

15
Marian

Ceci est un ancien post, mais je cherchais une réponse à cette même question,

Pourquoi ne pas essayer quelque chose comme:

scale_color_manual(values = c("foo" = "#999999", "bar" = "#E69F00"))

Si vous avez des valeurs catégoriques, je ne vois pas pourquoi cela ne fonctionnerait pas.

6