2016-05-19 5 views
4

Gibt es eine Möglichkeit in ggplot2 ein geom_ribbon (oder ein anderes flächenbasiertes Geom) mit einem variierenden Alpha basierend auf der Punktdichte zu erzeugen?ggplot2: geom_ribbon mit Alpha abhängig von der Datendichte entlang der y-Achse für jedes x

Der folgende Code erzeugt 50 verrauschte Sinuswellen mit zufälligen x-Werten für jede Probe. Ich möchte nicht jeden einzelnen Punkt zeichnen, weil ich vielleicht tausend oder mehr Resamples möchte, also möchte ich all diese Punkte zusammenfassen.

Eine einfache Methode wäre, einen geom_ribbon zu zeichnen, der 95% Quantile abdeckt. Dies ist jedoch zunächst nicht so einfach zu berechnen, da die x-Werte nicht für jede Resample gleich sind; normalerweise würden Sie die punktweisen Quantile an jedem der 100 x Punkte berechnen.

Stattdessen würde ich gerne ein Band haben, das den gesamten Bereich der Proben mit einem kontinuierlichen Alpha-Gradienten abdeckt, d. H. Das Band wäre am dunkelsten in der Mitte nahe der tatsächlichen Linie und sehr hell an den Ausreißern. Ist das in ggplot2 möglich?

library(ggplot2) 

num_points = 100 
num_samples = 50 

x = seq(0, 4*pi, length.out=num_points) 

sim <- lapply(1:num_samples, function(f) { 
    x = runif(num_points, 0, 4*pi) 
    y = sin(x) + rnorm(num_points, 0, 0.4) 
    data.frame(x=x, y=y) 
}) 

sim.df <- do.call(rbind, sim) 
actual = data.frame(x=x, y=sin(x)) 

ggplot(sim.df, aes(x=x, y=y)) + 
    geom_point(alpha=0.7) + 
    geom_line(data=actual, colour='blue', size=1.5) 

Plot of noisy sinewaves

Antwort

8

Eine Option ist Quantilsregression zu bekommen die y-Werte für jedes Quantil an jedem x-Wert zu verwenden und dann diejenigen geom_ribbon mit plotten.

library(splines) 
library(quantreg) 
library(reshape2) 
library(dplyr) 
  1. Set Quantile für Dichte Bänder:

    nq = 50 # Numbre of quantiles 
    qq = seq(0,1, length.out=nq) 
    
  2. Führen Sie die Quantilsregression für jedes Quantil.

    m1 = rq(y ~ ns(x,10), data=sim.df, tau=qq) 
    
  3. Erstellen von Datenrahmen für die Verwendung durch geom_ribbon plotten Dichte quantiles: Ich habe eine flexible Spline-Funktion erhalten eine gute Anpassung an die Sinusfunktion verwendet.

    einen Datenrahmen von Regressions erstellen Quantil Prognosen predict Verwendung:

    xvals = seq(min(sim.df$x), max(sim.df$x), length.out=100) 
    rqs = data.frame(x=xvals, predict(m1, newdata=data.frame(x=xvals))) 
    names(rqs) = c("x", paste0("p",100*qq)) 
    

    die Daten umformen, so daß die Vorhersagen für jede Quantil als für eine Quantil und die ymin für die nächste Quantil ihnen ymax dienen (mit die Ausnahme, dass das erste Quantil nur einmal als erstes ymin dient und das letzte Quantil nur einmal als letztes dient ymax). Legen Sie die Daten im Langformat, damit wir Gruppe von Quantil in ggplot:

    dat1 = rqs[, -length(rqs)] 
    names(dat1)[-1] = paste0(names(dat1)[-1]) 
    dat2 = rqs[, -2] 
    names(dat2)[-1] = paste0(names(dat1)[-1]) 
    
    dat1 = melt(dat1, id.var="x") 
    names(dat1) = c("x","group","min") 
    dat2 = melt(dat2, id.var="x") 
    names(dat2) = c("x","group1","max") 
    
    dat = bind_cols(dat1, dat2) 
    
  4. nun das Grundstück erstellen. Wir ordnen die Quantile der alpha Ästhetik zu und verwenden dann scale_alpha_manual, um die Alpha-Werte für Quantile, die näher bei 0 liegen, höher zu setzen.5 und niedriger für quantiles näher an 0 und 1:

    ggplot() + 
        geom_point(data=sim.df, aes(x,y), alpha=0.1, size=0.5, colour="red") + 
        geom_ribbon(data=dat, aes(x=x, ymin=min, ymax=max, group=group, alpha=group), 
          fill="blue", lwd=0, show.legend=FALSE) + 
        theme_bw() + 
        scale_alpha_manual(values=c(seq(0.05,0.9,length.out=floor(0.5*length(qq))), 
               seq(0.9,0.05,length.out=floor(0.5*length(qq))))) 
    

enter image description here

Hier ist ein weiteres Beispiel, aber mit Daten, die eine variierende Standardabweichung hat:

sim <- lapply(1:num_samples, function(f) { 
    x = runif(num_points, 0, 4*pi) 
    y = sin(x) + rnorm(num_points, 0, abs(0.7*cos(x))+0.1) 
    data.frame(x=x, y=y) 
}) 

sim.df <- do.call(rbind, sim) 

Jetzt nur noch laufen All den Code, den wir zuvor erstellt haben, um dieses Diagramm zu erhalten:

enter image description here

+0

Perfekt, danke. Nur eine Anmerkung für diejenigen, die größere Datenmengen verwenden, müssen Sie Alpha = sort (group) im geom_ribbon-Aufruf festlegen, da andernfalls angenommen wird, dass Gruppe 59 das nächste Quantil von 591 ist. –