简体   繁体   中英

ggplot2: geom_bar with group, position_dodge and fill

I am trying to generate a barplot such that the x-axes is by patient with each patient having multiple samples. So for instance (using the mtcars data as a template of what the data would look like):

library("ggplot2")
ggplot(mtcars, aes(x = factor(cyl), group = factor(gear))) +
   geom_bar(position = position_dodge(width = 0.8), binwidth = 25) +
   xlab("Patient") +
   ylab("Number of Mutations per Patient Sample")

This would produce something like this:

在此处输入图像描述

With each barplot representing a sample in each patient.

I want to add additional information about each patient sample by using colors to fill the barplots (eg different types of mutations in each patient sample). I was thinking I could specify the fill parameter like this:

ggplot(mtcars, aes(x = factor(cyl), group = factor(gear), fill = factor(vs))) +
   geom_bar(position = position_dodge(width = 0.8), binwidth = 25) +
   xlab("Patient") +
   ylab("Number of Mutations per Patient Sample")

But this doesn't produce "stacked barplots" for each patient sample barplot. I am assuming this is because the position_dodge() is set. Is there anyway to get around this? Basically, what I want is:

ggplot(mtcars, aes(x = factor(cyl), fill = factor(vs))) +
   geom_bar() +
   xlab("Patient") +
   ylab("Number of Mutations per Patient Sample")

在此处输入图像描述

But with these colors available in the first plot I listed. Is this possible with ggplot2?

I think facets are the closest approximation to what you seem to be looking for:

ggplot(mtcars, aes(x = factor(gear), fill = factor(vs))) +
    geom_bar(position = position_dodge(width = 0.8), binwidth = 25) +
    xlab("Patient") +
    ylab("Number of Mutations per Patient Sample") +
    facet_wrap(~cyl)

情节结果

I haven't found anything related in the issue tracker of ggplot2.

I have hacked around this a few times by layering multiple geom_cols on top of each other in the order I prefer. For example, the code

    ggplot(data, aes(x=cert, y=pct, fill=Party, group=Treatment, shape=Treatment)) +
      geom_col(aes(x=cert, y=1), position=position_dodge(width=.9), fill="gray90") +
      geom_col(position=position_dodge(width=.9)) +
      scale_fill_manual(values=c("gray90", "gray60"))

Allowed me to produce the feature you're looking for without faceting. Notice how I set the background layer's y value to 1. To add more layers, you can just cumulatively sum your variables.

Image of the plot:

情节

If I understand your question correctly, you want to pass in aes() into your geom_bar layer. This will allow you to pass a fill aesthetic. You can then place your bars as "dodge" or "fill" depending on how you want to display the data.

A short example is listed here:

   ggplot(mtcars, aes(x = factor(cyl), fill = factor(vs))) +
      geom_bar(aes(fill = factor(vs)), position = "dodge", binwidth = 25) +
      xlab("Patient") +
      ylab("Number of Mutations per Patient Sample")

With the resulting plot: http://imgur.com/ApUJ4p2 (sorry S/O won't let me post images yet)

Hope that helps!

I guess, my answer in this post will help you to build the chart with multiple stacked vertical bars for each patient ...

Layered axes in ggplot?

One way I don't see suggested above is to use facet_wrap to group samples by patient and then stack mutations by sample. Removes the need for dodging. Also changed and modified which mtcars attributes used to match question and get more variety in the mutations attribute.

    patients <-c('Tom','Harry','Sally')
    samples <- c('S1','S2','S3')
    mutations <- c('M1','M2','M3','M4','M5','M6','M7','M8')
    
    ds <- data.frame(
        patients=patients[mtcars$cyl/2 - 1],
        samples=samples[mtcars$gear - 2],
        mutations=mutations[mtcars$carb]
    )
    ggplot(
        ds, 
        aes(
            x      = factor(samples), 
            group  = factor(mutations),
            fill   = factor(mutations)
        )
    ) +
       geom_bar() +
       facet_wrap(~patients,nrow=1) +
       ggtitle('Patient') +
       xlab('Sample') +
       ylab('Number of Mutations per Patient Sample') +
       labs(fill = 'Mutation')

Output now has labels that match the specific language of the request...easier to see what is going on.

情节的形象

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM