2012-03-12 4 views
13

Il existe un fewposts concernant l'utilisation de zones ombrées dans ggplot2, mais je ne pense pas que répondre exactement à ma question. J'ai deux pentes pour les lignes à travers un certain nombre de conditions, et je voudrais ombrer la région entre eux. Voici les données exemple:r - ggplot2 - créer une région ombrée entre deux couches geom_abline

dat <- data.frame(cond1=c("a","a","b","b"), 
       cond2=c("c","d","c","d"), 
       x=c(1,5), 
       y=c(1,5), 
       sl=c(1,1.2,0.9,1.1), 
       int=c(0,0.1,0.1,0), 
       slopeU=c(1.1,1.3,1.2,1.2), 
       slopeL=c(.9,1,0.7,1)) 

Ici, sl est le paramètre de pente moyenne à partir d'une procédure d'ajustement séparé, et slopeU et slopeL représentent des régions de confiance supérieur et inférieur sur l'estimation de la pente dans chaque condition. Les interceptions sont contraintes à être les mêmes. Le code suivant trace les meilleures lignes de montage pour chaque condition à l'aide de certains facettage:

p <- ggplot(dat,aes(x=x,y=y,colour=cond1)) 
p <- p + facet_grid(. ~ cond2) 
p <- p + geom_blank() 
p <- p + geom_abline(aes(intercept=int,slope=sl,colour=cond1),data=dat) 
p 

Je voudrais ajouter les lignes définies par intercept=int, slope=slopeU et intercept=int, slope=slopeL à la parcelle et l'ombre de la région entre eux (par exemple à alpha=.5 dans le correspondant couleur cond1).

Je reconnais qu'avec un peu de manipulation je pourrais créer un cadre de données spécifiant les valeurs de ces lignes pour au moins deux valeurs x, puis tracer le geom_ribbon ou geom_polygon correspondant pour créer la région ombrée, mais je voudrais trouver plus solution élégante. Ou spécifie-t-il manuellement certaines coordonnées depuis les pentes et intercepte le seul chemin? Comment puis-je créer au mieux la trame de données requise (qui devra avoir plus de lignes que la trame d'origine pour tenir compte de toutes les combinaisons de conditions et de paires x, y).

Répondre

10

Personnellement, je pense que la création des trames de données et en utilisant geom_ribbonest la solution élégante, mais évidemment les opinions seront différentes sur ce point.

Mais si vous profitez pleinement de plyr et ggplot choses peuvent être assez lisse. Étant donné que vos pistes et Intercepts sont tous bien stockés dans une trame de données de toute façon, nous pouvons utiliser plyr et une fonction personnalisée pour faire tout le travail:

dat <- data.frame(cond1=c("a","a","b","b"), 
      cond2=c("c","d","c","d"), 
      x=c(1,5), 
      y=c(1,5), 
      sl=c(1,1.2,0.9,1.1), 
      int=c(0,0.1,0.1,0), 
      slopeU=c(1.1,1.3,1.2,1.2), 
      slopeL=c(.9,1,0.7,1)) 

genRibbon <- function(param,xrng){ 
    #xrng is a vector of min/max x vals in original data 
    r <- abs(diff(xrng)) 
    #adj for plot region expansion 
    x <- seq(xrng[1] - 0.05*r,xrng[2] + 0.05*r,length.out = 3) 
    #create data frame 
    res <- data.frame(cond1 = param$cond1, 
         cond2 = param$cond2, 
         x = x, 
         y = param$int + param$sl * x, 
         ymin = param$int + param$slopeL * x, 
         ymax = param$int + param$slopeU * x) 
    #Toss the min/max x vals just to be safe; needed them 
    # only to get the corresponding y vals 
    res$x[which.min(res$x)] <- -Inf 
    res$x[which.max(res$x)] <- Inf 
    #Return the correspondinng geom_ribbon 
    geom_ribbon(data = res,aes(x = x,y=y, ymin = ymin,ymax = ymax, 
           fill = cond1,colour = NULL), 
       alpha = 0.5) 
} 

ribs <- dlply(dat,.(cond1,cond2),genRibbon,xrng = c(1,5)) 

La chose lisse supplémentaire est que je ici me jeter la généré des trames de données complètement et juste renvoyer une liste d'objets geom_ribbon. Ensuite, ils peuvent tout simplement être ajouté à notre parcelle:

p + ribs + 
    guides(fill = guide_legend(override.aes = list(alpha = 0.1))) 

Je l'emporterait sur l'esthétique alpha dans la légende parce que la première fois que vous ne pouvait pas voir les lignes diagonales dans la légende.

enter image description here

Je vous préviens que la dernière ligne il qui génère les parcelles jette aussi beaucoup d'avertissements sur les niveaux de facteur invalides, et je suis honnêtement ne sais pas pourquoi. Mais l'intrigue semble ok.

+0

C'est génial; merci Joran. – tsawallis

+0

Donc, cela fonctionne essentiellement avec mon problème appliqué, mais je ne peux pas obtenir les couleurs sur les régions ombrées à cond1, même en exécutant votre solution exactement. Les régions de ruban remplies sont grises (à alpha = 0,5) mais ont également des bordures de ligne continues minces. Où vais-je mal? Serait-ce une différence de version de ggplot2? Je suis sur 0.9.0. La commande ggplot que j'utilise est comme dans le post original, avec 'p + côtes + guides (fill = guide_legend (override.aes ​​= liste (alpha = 0.1)))' collé ci-dessous. – tsawallis

+0

@waldog Désolé, juste un peu manqué lors de la copie + coller mon code.Vous n'avez qu'à ajouter 'fill = cond1' dans' aes() 'soit dans l'appel' ggplot() 'de niveau supérieur, soit dans l'appel' geom_ribbon' dans la fonction. Je vais éditer momentanément ... – joran

Questions connexes