web-dev-qa-db-fra.com

ggplot2: comportement de couleur de remplissage de geom_ribbon

J'essaie de colorer des rubans dans ggplot2. Lorsque j'utilise geom_ribbon, je peux spécifier ymin et ymax et une couleur de remplissage. Ce qu'il fait maintenant, c'est colorer tout ce qui est entre ymin et ymax sans égard à la limite supérieure ou inférieure.

Exemple (modifié depuis Internet):

library("ggplot2")
# Generate data (level2 == level1)
huron <- data.frame(year = 1875:1972, level = as.vector(LakeHuron), level2 = as.vector(LakeHuron))

# Change Level2
huron[1:50,2] <- huron[1:50,2]+100
huron[50:90,2] <- huron[50:90,2]-100

h <- ggplot(huron, aes(year))

h +
  geom_ribbon(aes(ymin = level, ymax = level2), fill = "grey80") +
  geom_line(aes(y = level)) + geom_line(aes(y=level2))

se traduira par ce graphique: enter image description here

Je voudrais remplir la zone, où (ymin> ymax), avec une couleur différente de celle où (ymin <ymax). Dans mes données réelles, j'ai des valeurs d'exportation et d'importation. Là, je voudrais colorer la zone où l'exportation est supérieure à l'importation verte, où l'importation est plus grande que l'exportation. Je veux que le ruban soit rouge.

Alternative: je voudrais que geom_ribbon remplisse uniquement la zone, où ymax> ymin.

Quelqu'un sait-il comment procéder?

Merci de votre aide.

13
ManuK

Une option qui ne nécessite pas de créer manuellement une autre colonne serait de faire la logique dans aes(fill = lui-même;

## fill dependent on level > level2
h + 
  geom_ribbon(aes(ymin = level, ymax = level2, fill = level > level2)) +
  geom_line(aes(y = level)) + geom_line(aes(y=level2)) +
  scale_fill_manual(values=c("red", "green"), name="fill")

filled conditional on level > level2

Ou, si vous ne souhaitez remplir cette condition que si cette condition est vraie,

## fill dependent on level > level2, no fill otherwise
h + 
  geom_ribbon(aes(ymin = level, ymax = level2, fill = ifelse(level > level2, TRUE, NA))) +
  geom_line(aes(y = level)) + geom_line(aes(y=level2)) +
  scale_fill_manual(values=c("green"), name="fill")

filled conditional on level > level2, not otherwise

Je suppose que le manque de remplissage interpolé semble avoir quelque chose à voir avec le ggplot2 version, car je reçois la même chose avec le code de @ beetroot

## @beetroot's answer
huron$id <- 1:nrow(huron)
huron$group <- ifelse(huron$id <= 50, "A", "B") 

h <- ggplot(huron, aes(year))
h +
  geom_ribbon(aes(ymin = level, ymax = level2, fill = group)) +
  geom_line(aes(y = level)) + geom_line(aes(y = level2))    

@beetroot's answer

J'obtiens la sortie d'image de @ ManuK lors de l'exécution de ce code sans logique dans aes(fill =.

14
Jonathan Carroll

Vous pouvez ajouter une variable de regroupement aux données que vous pouvez utiliser pour spécifier la couleur de remplissage. Cependant, le problème est le point où les deux lignes se croisent car il doit être inclus dans les deux groupes pour éviter tout écart.

Alors, trouvez d'abord cette ligne ..

huron[huron$level == huron$level2,]

> huron[huron$level == huron$level2,]
     year  level level2 
50   1924 577.79 577.79 
...

Et ajoutez-le aux données une fois de plus:

huron <- rbind(huron, huron[huron$year == 1924,])
huron <- huron[order(huron$year),]

Ajoutez ensuite une colonne id basée sur l'index de ligne et définissez les groupes en fonction du numéro de ligne de l'année 1924:

huron$id <- 1:nrow(huron)
huron$group <- ifelse(huron$id <= 50, "A", "B") 

h <- ggplot(huron, aes(year))
h +
  geom_ribbon(aes(ymin = level, ymax = level2, fill = group)) +
  geom_line(aes(y = level)) + geom_line(aes(y = level2))

enter image description here

6
beetroot

Pour contourner le problème que j'ai rencontré avec les fill non interpolés, vous pouvez utiliser deux (ou n) rubans

h <- ggplot() +
  geom_ribbon(data = huron[huron$level >= huron$level2, ], aes(x = year, ymin = level, ymax = level2), fill="green") +
  geom_ribbon(data = huron[huron$level <= huron$level2, ], aes(x = year, ymin = level, ymax = level2), fill="red") +
  geom_line(data = huron, aes(x = year, y = level)) + 
  geom_line(data = huron, aes(x = year, y = level2))
h

Fill is interpolated now

Toute condition que vous utilisez dans aes(fill = va le contraindre à un facteur, il semble donc ne s'appliquer que là où se trouvent réellement les données. Je ne pense pas que ce soit un ggplot2 bug, je pense que c'est un comportement attendu.

4
Jonathan Carroll