2016-01-08 10 views
6

Provo ad utilizzare la nuova funzionalità di ggplot2 in R che consente di creare le nostre funzioni stat_. Sto creando uno semplice per calcolare e tracciare una superficie interpolata tra punti disposti su un array 2d.ggplot2 2.0 nuova funzione stat_: impostazione della scala predefinita per l'estetica data

Vorrei creare uno stat_topo() richiede x, y e val estetica, tracciando una semplice geom_raster di interpolati val mappato fill.

library(ggplot2) 
library(dplyr) 
library(akima) 

cpt_grp <- function(data, scales) { 
    #interpolate data in 2D 
    itrp <- akima::interp(data$x,data$y,data$val,linear=F,extrap=T) 
    out <- expand.grid(x=itrp$x, y=itrp$y,KEEP.OUT.ATTRS = F)%>% 
    mutate(fill=as.vector(itrp$z)) 
    # str(out) 
    return(out) 
} 

StatTopo <- ggproto("StatTopo", Stat, 
        compute_group = cpt_grp, 
        required_aes = c("x","y","val") 
) 
stat_topo <- function(mapping = NULL, data = NULL, geom = "raster", 
         position = "identity", na.rm = FALSE, show.legend = NA, 
         inherit.aes = TRUE, ...) { 
    layer(
    stat = StatTopo, data = data, mapping = mapping, geom = geom, 
    position = position, show.legend = show.legend, inherit.aes = inherit.aes, 
    params = list(na.rm = na.rm, ...) 
) 
} 

set.seed(1) 
nchan <- 30 
d <- data.frame(val = rnorm(nchan), # some random values to be mapped to fill color 
     x = 1:nchan*cos(1:nchan), # the x and y position of the points to interpolate 
     y = 1:nchan*sin(1:nchan)) 
plot(d$x,d$y) 

ggplot(d,aes(x=x,y=y,val=val)) + 
    stat_topo() + 
    geom_point() 

Quando eseguo questo, ottengo il seguente errore:

Error: numerical color values must be >= 0, found -1 

Capisco che questo è perché in qualche modo la scala del fill estetica è impostato su discreti.

Se entro questo:

ggplot(d,aes(x=x,y=y,val=val)) + 
    stat_topo() + 
    scale_fill_continuous() + 
    geom_point() 

ottengo quello che volevo: il raster atteso con una scala di colori in continuo, che voglio il stat_ da fare di default ...

enter image description here

Quindi suppongo che la domanda sia: Come posso impedire a ggplot di impostare una scala discreta qui e idealmente impostare una scala predefinita all'interno della chiamata alla mia nuova funzione stat_.

+0

I tipi di che hai bisogno di avere una coppia 'geom' andare con il vostro stat per ottenere ciò che si desidera per impostazione predefinita. –

risposta

2

Apparentemente, quando si crea una nuova variabile all'interno di una funzione stat_, è necessario associarla esplicitamente all'estetica a cui verrà associata con il parametro default_aes = aes(fill = ..fill..) all'interno della definizione ggproto.

Questo sta dicendo a ggplot che si tratta di un'estetica calcolata e selezionerà una scala in base al tipo di dati.

Quindi qui abbiamo bisogno di definire il stat_ come segue:

cpt_grp <- function(data, scales) { 
    # interpolate data in 2D 
    itrp <- akima::interp(data$x,data$y,data$val,linear=F,extrap=T) 
    out <- expand.grid(x=itrp$x, y=itrp$y,KEEP.OUT.ATTRS = F)%>% 
    mutate(fill=as.vector(itrp$z)) 
    # str(out) 
    return(out) 
} 

StatTopo <- ggproto("StatTopo", Stat, 
        compute_group = cpt_grp, 
        required_aes = c("x","y","val"), 
        default_aes = aes(fill = ..fill..) 
) 

stat_topo <- function(mapping = NULL, data = NULL, geom = "raster", 
         position = "identity", na.rm = FALSE, show.legend = NA, 
         inherit.aes = TRUE, ...) { 
    layer(
    stat = StatTopo, data = data, mapping = mapping, geom = geom, 
    position = position, show.legend = show.legend, inherit.aes = inherit.aes, 
    params = list(na.rm = na.rm, ...)  
) 
} 

Poi il seguente codice:

set.seed(1) 
nchan <- 30 
d <- data.frame(val = rnorm(nchan), 
       x = 1:nchan*cos(1:nchan), 
       y = 1:nchan*sin(1:nchan)) 
ggplot(d,aes(x=x,y=y,val=val)) + 
    stat_topo() + 
    geom_point() 

Produce come previsto:

The result of stat_topo

Senza la necessità per specificare un scale_ m anualmente, ma lasciando la possibilità di adattare facilmente la scala come al solito ad es.scale_fill_gradient2(low = 'blue',mid='white',high='red')

ho avuto questa risposta qui: https://github.com/hadley/ggplot2/issues/1481

+0

Hey, hai rubato 15 punti indietro da me. –

1

Okay, ho dormito e ho avuto un'idea, e penso che questo potrebbe fare ciò che vuoi. Nella tua funzione di livello stat_topo anziché ggproto ho restituito un elenco con esso come primo elemento e poi aggiunto a quell'elenco un altro ggproto con una chiamata a scale_fill_continuous().

library(ggplot2) 
library(dplyr) 
library(akima) 

cpt_grp <- function(data, scales) { 
    #interpolate data in 2D 
    itrp <- akima::interp(data$x,data$y,data$val,linear=F,extrap=T) 
    out <- expand.grid(x=itrp$x, y=itrp$y,KEEP.OUT.ATTRS = F)%>% 
    mutate(fill=as.vector(itrp$z)) 
    return(out) 
} 
StatTopo <- ggproto("StatTopo", Stat, 
        compute_group = cpt_grp, 
        required_aes = c("x","y","val") 
) 
stat_topo <- function(mapping = NULL, data = NULL, geom = "raster", 
         position = "identity", na.rm = FALSE, show.legend = NA, 
         inherit.aes = TRUE, ...) { 
    list(
    layer(
     stat = StatTopo, data = data, mapping = mapping, geom = geom, 
     position = position, show.legend = show.legend, inherit.aes = inherit.aes, 
     params = list(na.rm = na.rm) 
    ), 
    scale_fill_continuous() 
) 
} 
set.seed(1) 
nchan <- 30 
d <- data.frame(val = rnorm(nchan), # some random values to be mapped to fill color 
       x = 1:nchan*cos(1:nchan), # the x and y position of interp points 
       y = 1:nchan*sin(1:nchan)) 
ggplot(d,aes(x=x,y=y,val=val)) + 
    stat_topo() + 
    geom_point() 

restituendo la stessa immagine di cui sopra.

+0

fantastico, grazie! la chiave stava creando la lista in stat_topo. Ho provato ad aggiungerli prima ma non volevo. – Max

+0

Ancora sembra che ci sia qualcosa di sospetto nel modo in cui i valori sono mappati all'estetica 'fill' qui. Ho presentato un problema su ggplot github. – Max

Problemi correlati