How to add legend in a ggplot2 bar chart

2019-05-28 18:22发布

I am trying to design a nice graph in ggplot2 by using bars to show different values for some periods. I got the graphic but I can't add the legend in the rigth side of the graph. My dataframe DF has 3 variables Month,variable,value. These variables are the result of melt() function in another data (I add the dput() version of DF in the final part). So, my dataframe DF looks like this:

   Month variable     value
1     m2    Power 1258978.9
2     m3    Power 1608317.4
3     m4    Power 1293821.1
4     m5    Power 1819283.8
5     m6    Power 1436552.9
6     m7    Power  875170.3
7     m8    Power 1315856.2
8     m9    Power  710004.3
9    m10    Power  889398.1
10   m11    Power 1114883.1
11   m12    Power 1419242.1
12   m13    Power 1585857.2
13   m14    Power 1010455.6
14   m15    Power 1292333.4

To show the evolution of value variable by month I used this code:

library(ggplot2)
library(scales)
ggplot(DF, aes(x = Month, y = value))+geom_bar(position="identity",fill="#FF6C91",colour="black",size=1)+ scale_y_continuous(labels = comma,breaks=pretty_breaks(n=7),limits=c(0,max(DF$value,na.rm=T)))+
  theme(axis.text.x=element_text(angle=90,colour="grey20",face="bold",size=12),axis.text.y=element_text(colour="grey20",face="bold",hjust=1,vjust=0.8,size=15),axis.title.x=element_text(colour="grey20",face="bold",size=16),axis.title.y=element_text(colour="grey20",face="bold",size=16))+xlab('Month')+ylab('')+ ggtitle("My graph")+theme(plot.title = element_text(lineheight=3, face="bold", color="black",size=24))+theme(legend.text=element_text(size=14),legend.title=element_text(size=14))

With this code I got the next graphic: enter image description here

The result is almost perfect but I don't know how to add the legend in the right side of the graph with the same color of bars to give more information in this image. I have tried to add fill argument inside geom_bar but I can't get my wished result. The dput() version of DF is the next:

DF=structure(list(Month = c("m2", "m3", "m4", "m5", "m6", "m7", 
"m8", "m9", "m10", "m11", "m12", "m13", "m14", "m15"), variable = structure(c(1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), .Label = "Power", class = "factor"), 
    value = c(1258978.86, 1608317.42, 1293821.14, 1819283.78, 
    1436552.93, 875170.34, 1315856.24, 710004.35, 889398.08, 
    1114883.11, 1419242.11, 1585857.22, 1010455.56, 1292333.35
    )), .Names = c("Month", "variable", "value"), row.names = c(NA, 
-14L), class = "data.frame")

Many thanks for your help.

标签: r ggplot2
3条回答
Deceive 欺骗
2楼-- · 2019-05-28 19:02

You need to map fill to an aesthetic to force a legend. From there, you can add whatever other information you want with scale_fill_manual

Here's the code (note I made a factor out of Month so the x-axis is in order, or atleast the order that I think you want):

DF$Month2 <- factor(DF$Month, levels = paste0("m", 2:15))

ggplot(DF, aes(x = Month2, y = value, fill = variable)) +
  geom_bar(stat="identity",colour="black",size=1) + #NOTE - you need stat = identity, not position
  scale_y_continuous(labels = comma,breaks=pretty_breaks(n=7),
                     limits=c(0,max(DF$value,na.rm=T))) +
  theme(axis.text.x=element_text(angle=90,colour="grey20",face="bold",size=12),
        axis.text.y=element_text(colour="grey20",face="bold",hjust=1,vjust=0.8,size=15),
        axis.title.x=element_text(colour="grey20",face="bold",size=16),
        axis.title.y=element_text(colour="grey20",face="bold",size=16)) +
  xlab('Month')+ylab('')+ ggtitle("My graph") +
  theme(plot.title = element_text(lineheight=3, face="bold", color="black",size=24)) +
  theme(legend.text=element_text(size=14),
        legend.title=element_text(size=14)) +
  scale_fill_manual(name = "This is stuff I made up", 
                    label = "This is stuff I made up II", 
                    values = "#FF6C91")

Giving you:

enter image description here

查看更多
太酷不给撩
3楼-- · 2019-05-28 19:14

You just need to make the fill part of the aesthetic mapping:

gg <- ggplot(DF, aes(x=Month, y=value))
gg <- gg + geom_bar(stat="identity", aes(fill=variable), colour="black", size=1)
gg <- gg + scale_y_continuous(labels=comma, breaks=pretty_breaks(n=7),
                              limits=c(0, max(DF$value,na.rm=T)))
gg <- gg + scale_fill_manual(values="#FF6C91", name="Legend name")
gg <- gg + labs(x="Month", y="", title="My graph")
gg <- gg + theme(plot.title=element_text(lineheight=3, face="bold", color="black", size=24))
gg <- gg + theme(legend.text=element_text(size=14), legend.title=element_text(size=14))
gg <- gg + theme(axis.text.x=element_text(angle=90, colour="grey20", face="bold", size=12), 
                 axis.text.y=element_text(colour="grey20", face="bold", hjust=1, vjust=0.8, size=15),
                 axis.title.x=element_text(colour="grey20", face="bold", size=16),
                 axis.title.y=element_text(colour="grey20", face="bold", size=16))
    gg

enter image description here

NOTE: I changed the position="identity" to stat="identity" (I think you prbly just mis-pasted since you did get it working), re-structured the ggplot to make it easier to modify (programmer's preference, not necessary to make it work) and then did a manual scale after mapping the fill aesthetic to the variable (and you can rename the legend title there, too, as demonstrated). It's that mapping which automagically enable the legend. I also threw in a theme_bw() call for good measure (and to nuke the grey background).

I would have rotate the x-axis labels back to horizontal, but didn't want to impose that as well. Making folks tilt their heads to read labels is usually not recommended, but since they are just m's and digits, it probably isn't going to be that hard.

It might be worth sorting the bars (lowest to highest or vice versa) unless you need them ordered the way they are on the x-axis (i.e. of the m10 - m9 order the way it is now is important).

查看更多
霸刀☆藐视天下
4楼-- · 2019-05-28 19:19

As others' have said, you need the fill specified in the aes. Here is another version, with a couple of further options for you to consider (legend name, and label and position, etc):

ForLeg=c(Power="#FF6C91");
    ggplot(DF, aes(x = Month, y=value, fill=as.factor(variable)))+
      geom_bar(stat="Identity",colour="black",size=1)+ 
      scale_fill_manual(values=ForLeg, labels="The value")+
      scale_y_continuous(labels = comma,breaks=pretty_breaks(n=7),limits=c(0,max(DF$value,na.rm=T)))+
      theme(axis.text.x=element_text(angle=90,colour="grey20",face="bold",size=12),axis.text.y=element_text(colour="grey20",face="bold",hjust=1,vjust=0.8,size=15),axis.title.x=element_text(colour="grey20",face="bold",size=16),axis.title.y=element_text(colour="grey20",face="bold",size=16))+
      xlab('Month')+
      ylab('')+ 
      ggtitle("My graph")+
      theme(plot.title = element_text(lineheight=3, face="bold", color="black",size=24))+
      theme(legend.position="top",legend.text=element_text(size=14),legend.title=element_text(size=14))+
      guides(fill=guide_legend(title="",keywidth = 2, keyheight = 1,title.position = "left",title.hjust = -0.28))

With the graph like: enter image description here

查看更多
登录 后发表回答