Overlay two bar plots with geom_bar()

2019-05-31 08:56发布

I'm trying to overlay two bar plots on top of each other, not beside. The data is from the same dataset. I want 'Block' on the x-axis and 'Start' and 'End' as overlaying bar plots.

    Block   Start       End
1    P1L     76.80       0.0
2    P1S     68.87       4.4
3    P2L     74.00       0.0
4    P2S     74.28       3.9
5    P3L     82.22       7.7
6    P3S     80.82      17.9

My script is

 ggplot(data=NULL,aes(x=Block))+
    geom_bar(data=my_data$Start,stat="identity",position ="identity",alpha=.3,fill='lightblue',color='lightblue4')+
    geom_bar(data=my_data$End,stat="identity",position ="identity",alpha=.8,fill='pink',color='red')

I get Error: ggplot2 doesn't know how to deal with data of class numeric

I've also tried

    ggplot(my_data,aes(x=Block,y=Start))+
      geom_bar(data=my_data$End, stat="identity",position="identity",...)

Anyone know how I can make it happen? Thank you.

Edit:

How to get dodge overlaying bars?

I edit this post, because my next question is relevant as it's the opposite problem of my original post.

@P.merkle

I had to change my plot into four bars showing the mean values of all Blocks labeled L and S. The L stand for littoral, and S for Sublittoral. They were exposed for two treatments: Normal and reduced.

I've calculated the means, and their standard deviation. I need four bars with their respective error bars: Normal/Littoral , Reduced/Littoral , Normal/Sublittoral , Reduced/Sublittoral.

Problem is when I plot it, both the littoral bars and both the sublittoral bars overlay each other! So now I want them not to overlap! How can i make it happen? I've tried all sorts of position = 'dodge' andposition = position_dodge(newdata$Force), without luck...

My newdata contain this information:

Zonation Force N mean sd se 1 Litoral Normal 6 0.000000 0.000000 0.000000 2 Litoral Redusert 6 5.873333 3.562868 1.454535 3 Sublitoral Normal 6 7.280000 2.898903 1.183472 4 Sublitoral Redusert 6 21.461667 4.153535 1.695674

My script is this:

ggplot(data=cdata,aes(x=newdata$Force,y=newdata$mean))+
        geom_bar(stat="identity",position ="dodge",
                 alpha=.4,fill='red', color='lightblue4',width = .6)+
        geom_errorbar(aes(ymin=newdata$mean-sd,ymax=newdata$mean+sd),
                      width=.2, position=position_dodge(.9))

The outcome is unfortunately this

As of the error bars, it's clearly four bars there, but they overlap. Please, how can I solve this?

1条回答
ら.Afraid
2楼-- · 2019-05-31 09:11

There is a simple, and a more complex answer to your question.

If you don't need a legend, the simple solution might work for you.

If you would like to display a legend next to the bar plot, consider using the more complex solution, which requires your data to be converted from wide format to long format.

Variant 1: Without legend, keeping data in wide format

You can refine your aesthetics specification on the level of individual geoms (here, geom_bar):

ggplot(data=my_data,aes(x=Block))+
  geom_bar(aes(y=Start),stat="identity",position ="identity",alpha=.3,fill='lightblue',color='lightblue4') +
  geom_bar(aes(y=End),stat="identity",position ="identity",alpha=.8,fill='pink',color='red')

plot without legend

Variant 2: Add legend by converting data to long format

To add a legend, use reshape2::melt to convert your data frame from wide format into long format, which gives you the columns variable ("Start" vs. "End"), and value. Then use the variable column to define your legend:

library(reshape2)
my_data_long <- melt(my_data, id.vars = c("Block"))
ggplot(data=my_data_long,aes(x=Block, y=value, fill=variable, color=variable, alpha=variable)) +
  geom_bar(stat="identity",position ="identity") +
  scale_colour_manual(values=c("lightblue4","red")) +
  scale_fill_manual(values=c("lightblue","pink")) +
  scale_alpha_manual(values=c(.3, .8))

enter image description here

查看更多
登录 后发表回答