Stacked histograms in R - as in flow cytometry

I am trying to use ggplot or plain R to generate something like the following:

enter image description here

I know how to make histograms using ggplot2 and split them easily using facet_grid or facet_wrap. But I would like to "wobble" them vertically so that they have some overlap, as shown below. Sorry I cannot post my own image and it is rather difficult to find a simpler image of what I want. If I could, I would only post the top left pane.

I realize this is not a very good way to display data, but this solution does not calm down.

An example dataset would be as follows:

my.data <- as.data.frame(rbind( cbind( rnorm(1e3), 1) , cbind( rnorm(1e3)+2, 2), cbind( rnorm(1e3)+3, 3), cbind( rnorm(1e3)+4, 4)))

      

And I can build it using geom_histogram like this:

ggplot(my.data) + geom_histogram(aes(x=V1,fill=as.factor(V2))) + facet_grid( V2~.)

      

But I would like the y-axes to overlap.

0


source to share


3 answers


require(ggplot2)
require(plyr)

my.data <- as.data.frame(rbind( cbind( rnorm(1e3), 1) , cbind(     rnorm(1e3)+2, 2), cbind( rnorm(1e3)+3, 3), cbind( rnorm(1e3)+4, 4)))
my.data$V2=as.factor(my.data$V2)

      

calculate density depending on V2

res <- dlply(my.data, .(V2), function(x) density(x$V1))
dd <- ldply(res, function(z){
  data.frame(Values = z[["x"]], 
             V1_density = z[["y"]],
             V1_count = z[["y"]]*z[["n"]])
})

      

add offset depending on V2



dd$offest=-as.numeric(dd$V2)*0.2 # adapt the 0.2 value as you need
dd$V1_density_offest=dd$V1_density+dd$offest

      

and plot

ggplot(dd, aes(Values, V1_density_offest, color=V2)) + 
  geom_line()+
  geom_ribbon(aes(Values, ymin=offest,ymax=V1_density_offest,     fill=V2),alpha=0.3)+
  scale_y_continuous(breaks=NULL)

      

results

+8


source


densityplot()

from the bioconductor package flowViz

is one of the addition density options.

from: http://www.bioconductor.org/packages/release/bioc/manuals/flowViz/man/flowViz.pdf :

For flowSets, the idea is to horizontally populate density estimates for all frames in the flowSet for one or more flow parameters. In the latter case, each parameter will be plotted on the chart in a separate panel, that is, we are implicitly setting the parameters.



you can see examples here: http://www.bioconductor.org/packages/release/bioc/vignettes/flowViz/inst/doc/filters.html

source("http://bioconductor.org/biocLite.R")
biocLite("flowViz")

      

+2


source


I think it will be difficult to get ggplot

to compensate for similar histograms. At least with faceting, it creates new panels, and indeed, this transformation makes the y-axis meaningless. (The value is compared from line to line). Here's one attempt at using basic graphics to try and accomplish a similar thing.

#plotting function
plotoffsethists <- function(vals, groups, freq=F, overlap=.25, alpha=.75, colors=apply(floor(rbind(col2rgb(scales:::hue_pal(h = c(0, 360) + 15, c = 100, l = 65)(nlevels(groups))),alpha=alpha*255)),2,function(x) {paste0("#",paste(sprintf("%02X",x),collapse=""))}), ...) {
    print(colors)
    if (!is.factor(groups)) {
        groups<-factor(groups)
    }
    offsethist <- function (x, col = NULL, offset=0, freq=F, ...) {
        y <- if (freq) y <- x$counts
        else 
            x$density
        nB <- length(x$breaks)
        rect(x$breaks[-nB], 0+offset, x$breaks[-1L], y+offset, col = col, ...)
    }

     hh<-tapply(vals, groups, hist, plot=F)

    ymax<-if(freq)
        sapply(hh, function(x) max(x$counts))
    else
        sapply(hh, function(x) max(x$density))
    offset<-(mean(ymax)*overlap) * (length(ymax)-1):0
    ylim<-range(c(0,ymax+offset))
    xlim<-range(sapply(hh, function(x) range(x$breaks)))
    plot.new()
    plot.window(xlim, ylim, "")
    box()
    axis(1)

    Map(offsethist, hh, colors, offset, freq=freq, ...)
    invisible(hh)
}

#sample call
par(mar=c(3,1,1,1)+.1)
plotoffsethists(my.data$V1, factor(my.data$V2), overlap=.25)

      

plotoffsethists example

+1


source







All Articles