7
votes

The following is my data:

chr <- rep (1:4, each = 200) 

position <- c(1:200, 1:200, 1:200, 1:200)

v1bar <- rnorm(800, 10, 2)

v2bar <- rnorm(800, 10, 2)

v3bar <- rnorm(800, 10, 2)

mydata <- data.frame (chr, position, v1bar, v2bar, v3bar)

I want to create multiple circular bar charts with the x value = pos and y value = v1bar, v2bar, v3bar (all three will be in successive circles). Each circle is divided to chr. Thus each circle has "pie slice". I am not sure what such graph is known as and would it be possible to develop one. The following just rough sketch to illustrate my idea.

enter image description here

Edits: My assuption is someway similar to the following circos figure.

http://circos.ca/tutorials/images/zoom/8.8

EDITS:

In response to the following answer to David, this what I have imagined - chr not seperate circe but classifying as different slice (such as in circos figure) enter image description here

2
rbloggers had a similar graph (histogram) discussed earlier this week CLICK HERETyler Rinker
What specifically do you want to include from the circos figure that my answer, for example, doesn't do?David Robinson
Your figure all features except (1) chr are different circle (instead of var) - which obivously can change easily (2) Chr are seperate slice of pie in addition to var in different circles - circos figure has this propertyjon
See my most recent addition- I think it's just what you're looking for.David Robinson
@JohnC: Did you take a look at my new answer?David Robinson

2 Answers

12
votes

Since you are presenting chromosomes in a circular way, try the tools provided by the ecolitk package provided by Bioconductor, which includes tools for plotting various kinds of shapes on circular chromosomes.

ETA: Here is an example of its use to create a circular bar plot, though it only scratches the surface of the things you can do with it.

circular plot

library(ecolitk)

plot.new()
plot.window(c(-5, 5), c(-5, 5))

plot.chrom = function(data, chromlength, radius=1,
                        width=chromlength/length(data), ...) {
    linesCircle(radius, ...)
    starts = seq(1, chromlength - width, width)

    scale = .5 / max(abs(data))
    for (i in 1:length(starts)) {
        polygonChrom(starts[i], starts[i]+width, chromlength, radius,
                data[i] * scale + radius, ...)
    }
}

plot.chrom(rnorm(100, 10, 1), 10000, radius=1)
plot.chrom(rnorm(100, 10, 2), 10000, radius=2, col="blue")
plot.chrom(rnorm(100, 10, 5), 10000, radius=3, col="red")
plot.chrom(rnorm(100, 10, 10), 10000, radius=4, col="green")

legend("topright", legend=c("chr1", "chr2", "chr3", "chr4"),
       col=c("black", "blue", "red", "green"), lty=1)

ETA: Ah, now I understand what you meant about division of plots. In that case, this code should be what you're looking for. It uses the data you present (with one slight modification- I had to give the chromosome column a name so I could use ddply with it) and allows you to specify the spacing between chromosomes. While I haven't tested it in depth, varying things like the individual chromosome lengths and the mean and variance of the simulated data should work as you expect.

Circular plot divided

plot.multi.chrom = function(data, colors, spacing=50) {
    plot.new()
    plot.window(c(-5, 5), c(-5, 5))

    lengths = ddply(data, .(chr), function(x) max(x$position))
    nchrom = NROW(lengths)
    offsets = cumsum(c(0, lengths[, 2])) + cumsum(c(0, rep(spacing, nchrom)))
    tot.length = offsets[length(offsets)] + spacing

    scales = .75 / apply(abs(data[, 3:NCOL(data)]), 2, max)

    for (i in 1:NROW(data)) {
        for (j in 3:NCOL(data)) {
            start = offsets[data[i, 1]] + data[i, 2]
            polygonChrom(start, start + 1, tot.length,
                         j - 2, data[i, j] * scales[j - 2] + j - 2,
                         col=colors[j - 2])
        }
    }
}

chr <- rep (1:4, each = 200) 
position <- c(1:200, 1:200, 1:200, 1:200)
v1bar <- rnorm(800, 10, 2)
v2bar <- rnorm(800, 10, 2)
v3bar <- rnorm(800, 10, 2)
mydata <- data.frame(chr=chr, position, v1bar, v2bar, v3bar)

 require(plyr) 

plot.multi.chrom(mydata, colors=c("red", "black", "green"), spacing=50)

legend("topright", legend=c("V1", "V2", "V3"),
       col=c("red", "black", "green"), lty=1)
0
votes

OmicCircos at R/Bioconductor has ability to draw overlayed circular multiple bar charts. OmicCircos's circos command takes argument, named cir where you can specify custom genome segments or chromosomes. For bar chart, it has argument type where you can specify one of bar plot, box plot, histogram, etc.

Check Vignette R script - code chunk number 14: OmicCircos4vignette1 for more.