有没有办法在barplot或ggplot的同一个图上使用barplot和堆叠的barplot? [英] Is there a way to have a barplot and a stacked barplot on the same graph using barplot or ggplot?
问题描述
我有两段数据要叠加到同一个图上。我已经看过几个ggplot文章,我认为它不可能在ggplot中。所以我一直在使用barplot。我有5层,我将每个层级的总美元作为一个坚实的标准。
然后我有另一块数据表示两种不同类型的工作人员在这些层中的任务数量。我把它当作一个堆积条形图。但我想在同一个图表上显示它们的总美元数量为一个条,然后在其旁边的相应堆积条。
以下是图:
第一张图的数据看起来像这样(这是一张表):
1 2 3 4 5
$ p
0 9 340 97 812 4271
1 1 417 156 3163 11314
$ b第二个图的数据如下所示(这是一个数据集):
等级变量值
1 1 Opp_Amt 16200.00
2 2 Opp_Amt 116067.50
3 3 Opp_Amt 35284.12
4 4 Opp_Amt 278107.10
5 5 Opp_Amt 694820.29
我想将图表放在彼此的顶部,但条形保持重叠,我希望它们显示在旁边一边一层。
代码为我到目前为止。
参数(mar = c(2.5,4,4,4)+2)
##第一组的数据并绘制其轴线
barplot(data1 $ value,axes = FALSE,ylim = c(0,700000),xlab =,ylab =,
col =black,space = -10,main =工作分数)
轴(2,ylim = c(0,700000),col =black,las = 1)## las = 1使水平标签
mtext(总机会数量,side = 2,line = 3.5)
box()
##在同一个图上允许第二个图
par(new = TRUE )
##绘制第二个图并将轴比例放在右边
m < - barplot(counts,xlab =,ylab =, ylim = c(0,16000),axes = FALSE,col = c(red,darkblue),space = 3,width = 0.5,density = 20)
##稍微远一些= 4)为标签
mtext(Task Ratio:Outbound to AE,side = 4,col =red,line = 3.5)腾出空间
轴(4,ylim = c(0 ,16000),col =red,col.axis =black,las = 1)
它给了我
解决方案使用ggplot
,我会做类似其中之一的事情。他们分别绘制两组数据。第一个将数据排列到一个数据框中,然后使用facet_wrap()
来并排定位图。第二个分别生成两个绘图对象,然后将这两个绘图和图例合并为一个组合绘图。
但是,如果你真的需要双y轴方法,那么在一些摆弄的情况下,使用图的布局和
gtable
函数,它可以完成(使用从这里借用的代码)。
像这样:
图书馆(ggplot2)
library(gtable)
library(plyr)
df1< - data.frame(Tier = rep(1:5,each = 2),
y = c(9,1,340,417,97,156,812,3063,4271,11314),
gp = rep(0:1,5))
df2 < - read.table(text =
Tier variable value
1 Opp_Amt 16200.00
2 Opp_Amt 116067.50
3 Opp_Amt 35284.12
4 Opp_Amt 278107.10
5 Opp_Amt 694820.29,header = TRUE)
dfA = df1
dfB = df2
名称(dfA)= c(Tier,Value, gp)
dfA $ var =任务比率
dfB = dfB [,c(1,3)]
dfB $ gp = 3
dfB $ var =Total机会金额
名称(dfB)=名称(dfA)
df = rbind(dfA,dfB)
df $ var =因子(df $ var)
df $ var =因子(df $ var,levels = rev(levels(df $ var)))
ggplot(df,aes(Tier,Value,fill = factor(gp)))+
geom_bar (position =stack,stat =identity)+
fac et_wrap(〜var,scale =free_y)+
scale_fill_manual(Group,breaks = c(0,1),values = c(#F8766D,#00BFC4, (),
panel.grid = element_blank())
theme_bw() code>
或者:p1 < - ggplot(df1,aes(factor(Tier),y,fill = factor(gp)))+
pre>
geom_bar =stack,stat =identity)+
#guides(fill = FALSE)+
scale_y_continuous(Task Ratio,
limit = c(0,1.1 * max(ddply (df1,。(Tier),sumrise,sum = sum(y)))),
expand = c(0,0))+
scale_x_discrete(Tier)+
theme_bw ()+
theme(panel.grid = element_blank())
p2 < - ggplot(df2,aes(factor(Tier),value))+
geom_bar stat =identity)+
scale_y_continuous(Total Opportunity Amount,limit = c(0,1.1 * max(df2 $ value)),expand = c(0,0))+
scale_x_discrete (第三级)+
theme_bw()+
theme(panel.grid = element_blank())
#获取ggplot grobs,
#从p1中获取图例
g1 < - ggplotGrob(p1)
leg = gtable_filter(g1,guide-box)
legColumn = g1 $ layout [which(g1 $ layout $ name ==guide- ),l]
g1 = g1 [, - legColumn]
g2 < - ggplotGrob(p2)
#确保宽度在g1中相同和g2
库(grid)
maxWidth = unit.pmax(g1 $ widths,g2 $ widths)
g1 $ widths = as.list(maxWidth)
g2 $ widths = as.list(maxWidth)
#合并g1,g2和图例
library(gridExtra)
grid.arrange(arrangeGrob(g2,g1,nrow = 1),leg,
widths = unit.c(unit(1,npc) - leg $ width,leg $ width),nrow = 1)
或双Y轴方法(但由于Phil's )
pre $ code $ width1 = 0.6#p1中的横条宽度
width2 = 0.2#p2中的横条宽度
pos = .5 * width1 + .5 * width2#p2中的定位条
p1 < - ggplot(df1,aes(factor(Tier),y,fill = factor(gp ))+
geom_bar(position =stack,stat =identity,width = width1)+
guides(fill = FALSE)+
scale_y_continuous(,
limit = c(0,1.1 * max(ddply(df1,。(Tier),summary,sum = sum(y)))),
expand = c(0,0))+
scale_x_discrete(Tier)+
theme_bw()+
theme(panel.grid = element_blank(),
axis.text.y = element_text(color =red,hjust = 0 ,margin = margin(l = 2,unit =pt)),
axis.ticks.y = element_line(color =red))
p2 < - ggplot( df2,aes(factor(Tier),value))+
geom_blank()+
geom_bar(aes(x = Tier - pos),stat =identity,width = width2)+
scale_y_continuous(,limit = c(0,1.1 * max(df2 $ value)),expand = c(0,0))+
theme_bw()+
theme(panel.grid = element_blank())
#获取ggplot grobs
g1< - (g1 $ layout,name = ggplotGrob)(p1)
g2 < - ggplotGrob(p2)
#获取g1
pp1 < - c =panel,se = t:r))
##从g2获取小节并将它们插入到g1
g中的面板中 - gtable_add_grob(g1,g2 $ grobs [ (g2 $ layout $ name ==panel)]] [[4]] [[4]],pp1 $ t,pp1 $ l)
#从g1中获取轴,反向元素,并将它放在正确的
index< - which(g1 $ layout $ name ==axis-l)
grob< - g1 $ grobs [[index]]
轴(< - grob $ children [[2]]
轴$宽度< - rev(轴$宽度)
轴$ grobs< - rev(轴$ grobs)
轴$ grobs [[1]] $ x < - axis $ grobs [[1]] $ x - unit(1,npc)+ unit(3,pt)
g < - gtable_add_cols(g,g1 $ widths [g1 $ layout [index,] $ l],pp1 $ r)
g < - gtable_add_grob(g,axis,pp1 $ t,pp1 $ l + 1)
#从g2获取坐标轴,并将其放在左边
index< - 其中(g2 $ layout $ name ==axis-l)
grob< - g2 $ grobs [[index]]
轴< - grob $ children [[2]]
g< - gt (g,rectGrob(gp = gpar(col = NA,fill =white)),pp1 $ t-1,pp1 $ 1-1,pp1 $ b + 1)
g < - gtable_add_grob(g ,axis,pp1 $ t,pp1 $ l-1)
#添加轴标题
#右轴标题
RightAxisText = textGrob(Task Ratio,rot = 90, gp = gpar(col =red))
g < - gtable_add_cols(g,unit.c(unit(1,grobwidth,RightAxisText)+ unit(1,line)),5)
g < - gtable_add_grob(g,RightAxisText,pp1 $ t,pp1 $ r + 2)
#左轴标题
LeftAxisText = textGrob(总机会金额,rot = 90)
g <-gtable_add_grob(g,LeftAxisText,pp1 $ t,pp1-1-2)
g $ widths [2]< - unit.c(unit(1,grobwidth,LeftAxisText )+ unit(1,line))
#绘制
grid.newpage()
grid.draw(g)
I have two pieces of data that I want to overlay onto the same plot. I've looked at several ggplot articles and I don't think it's possible within ggplot. So I have been using barplot. I have 5 tiers and I'm plotting total dollars by tier as a solid bar.
Then I have another piece of data that represents the number of tasks within those tiers by two different types of workers. I have this as a stacked bar plot. But I want to show them on the same graph with the total dollar amount as one bar and then the corresponding stacked bar next to it.
Here are the plots:
The data for the first graph looks like this (it's a table):
1 2 3 4 5 0 9 340 97 812 4271 1 1 417 156 3163 11314
The data for the second graph looks like this (this is a dataset):
Tier variable value 1 1 Opp_Amt 16200.00 2 2 Opp_Amt 116067.50 3 3 Opp_Amt 35284.12 4 4 Opp_Amt 278107.10 5 5 Opp_Amt 694820.29
I want to put the graphs on top of each other but the bars keep overlapping and I want them to appear side by side by tier.
Code for what I have so far.
par(mar=c(2.5, 4, 4, 4)+2) ## Plot first set of data and draw its axis barplot(data1$value, axes=FALSE,ylim=c(0,700000), xlab="", ylab="", col="black",space=-10,main="Work Score") axis(2, ylim=c(0,700000),col="black",las=1) ## las=1 makes horizontal labels mtext("Total Opportunity Amount",side=2,line=3.5) box() ## Allow a second plot on the same graph par(new=TRUE) ## Plot the second plot and put axis scale on right m <- barplot(counts, xlab="", ylab="", ylim=c(0,16000),axes=FALSE, col=c("red","darkblue"),space=3,width=0.5,density=20) ## a little farther out (line=4) to make room for labels mtext("Task Ratio: Outbound to AE",side=4,col="red",line=3.5) axis(4, ylim=c(0,16000), col="red",col.axis="black",las=1)
And it gives me this
解决方案Using
ggplot
, I would do something like one of these. They plot the two sets of data separately. The first arranges the data into one dataframe, then usesfacet_wrap()
to position the plots side-by-side. The second generates the two plot objects separately, then combines the two plots and the legend into a combined plot.But if you really need the "dual y-axis" approach, then with some fiddling, and using the plots' layouts and
gtable
functions, it can be done (using code borrowed from here).Like this:
library(ggplot2) library(gtable) library(plyr) df1 <- data.frame(Tier = rep(1:5, each = 2), y = c(9, 1, 340, 417, 97, 156, 812, 3063, 4271, 11314), gp = rep(0:1, 5)) df2 <- read.table(text = " Tier variable value 1 Opp_Amt 16200.00 2 Opp_Amt 116067.50 3 Opp_Amt 35284.12 4 Opp_Amt 278107.10 5 Opp_Amt 694820.29", header = TRUE) dfA = df1 dfB = df2 names(dfA) = c("Tier", "Value", "gp") dfA$var = "Task Ratio" dfB = dfB[,c(1,3)] dfB$gp = 3 dfB$var = "Total Opportunity Amount" names(dfB) = names(dfA) df = rbind(dfA, dfB) df$var = factor(df$var) df$var = factor(df$var, levels = rev(levels(df$var))) ggplot(df, aes(Tier, Value, fill = factor(gp))) + geom_bar(position = "stack", stat = "identity") + facet_wrap( ~ var, scale = "free_y") + scale_fill_manual("Group", breaks = c("0","1"), values = c("#F8766D", "#00BFC4", "black")) + theme_bw() + theme(panel.spacing = unit(2, "lines"), panel.grid = element_blank())
Or this:p1 <- ggplot(df1, aes(factor(Tier), y, fill = factor(gp))) + geom_bar(position = "stack", stat = "identity") + #guides(fill = FALSE) + scale_y_continuous("Task Ratio", limit = c(0, 1.1*max(ddply(df1, .(Tier), summarise, sum = sum(y)))), expand = c(0,0)) + scale_x_discrete("Tier") + theme_bw() + theme(panel.grid = element_blank()) p2 <- ggplot(df2, aes(factor(Tier), value)) + geom_bar(stat = "identity") + scale_y_continuous("Total Opportunity Amount", limit = c(0, 1.1*max(df2$value)), expand = c(0,0)) + scale_x_discrete("Tier") + theme_bw() + theme(panel.grid = element_blank()) # Get the ggplot grobs, # And get the legend from p1 g1 <- ggplotGrob(p1) leg = gtable_filter(g1, "guide-box") legColumn = g1$layout[which(g1$layout$name == "guide-box"), "l"] g1 = g1[,-legColumn] g2 <- ggplotGrob(p2) # Make sure the width are the same in g1 and g2 library(grid) maxWidth = unit.pmax(g1$widths, g2$widths) g1$widths = as.list(maxWidth) g2$widths = as.list(maxWidth) # Combine g1, g2 and the legend library(gridExtra) grid.arrange(arrangeGrob(g2, g1, nrow = 1), leg, widths = unit.c(unit(1, "npc") - leg$width, leg$width), nrow=1)
Or the dual y-axis approach (But not recommended for reasons given in @Phil's post):width1 = 0.6 # width of bars in p1 width2 = 0.2 # width of bars in p2 pos = .5*width1 + .5*width2 # positioning bars in p2 p1 <- ggplot(df1, aes(factor(Tier), y, fill = factor(gp))) + geom_bar(position = "stack", stat = "identity", width = width1) + guides(fill = FALSE) + scale_y_continuous("", limit = c(0, 1.1*max(ddply(df1, .(Tier), summarise, sum = sum(y)))), expand = c(0,0)) + scale_x_discrete("Tier") + theme_bw() + theme(panel.grid = element_blank(), axis.text.y = element_text(colour = "red", hjust = 0, margin = margin(l = 2, unit = "pt")), axis.ticks.y = element_line(colour = "red")) p2 <- ggplot(df2, aes(factor(Tier), value)) + geom_blank() + geom_bar(aes(x = Tier - pos), stat = "identity", width = width2) + scale_y_continuous("", limit = c(0, 1.1*max(df2$value)), expand = c(0,0)) + theme_bw() + theme(panel.grid = element_blank()) # Get ggplot grobs g1 <- ggplotGrob(p1) g2 <- ggplotGrob(p2) # Get locations of the panels in g1 pp1 <- c(subset(g1$layout, name == "panel", se = t:r)) ## Get bars from g2 and insert them into the panel in g1 g <- gtable_add_grob(g1, g2$grobs[[which(g2$layout$name == "panel")]][[4]][[4]], pp1$t, pp1$l) # Grab axis from g1, reverse elements, and put it on the right index <- which(g1$layout$name == "axis-l") grob <- g1$grobs[[index]] axis <- grob$children[[2]] axis$widths <- rev(axis$widths) axis$grobs <- rev(axis$grobs) axis$grobs[[1]]$x <- axis$grobs[[1]]$x - unit(1, "npc") + unit(3, "pt") g <- gtable_add_cols(g, g1$widths[g1$layout[index, ]$l], pp1$r) g <- gtable_add_grob(g, axis, pp1$t, pp1$l+1) # Grab axis from g2, and put it on the left index <- which(g2$layout$name == "axis-l") grob <- g2$grobs[[index]] axis <- grob$children[[2]] g <- gtable_add_grob(g, rectGrob(gp = gpar(col = NA, fill = "white")), pp1$t-1, pp1$l-1, pp1$b+1) g <- gtable_add_grob(g, axis, pp1$t, pp1$l-1) # Add axis titles # right axis title RightAxisText = textGrob("Task Ratio", rot = 90, gp = gpar(col = "red")) g <- gtable_add_cols(g, unit.c(unit(1, "grobwidth", RightAxisText) + unit(1, "line")), 5) g <- gtable_add_grob(g, RightAxisText, pp1$t, pp1$r+2) # left axis title LeftAxisText = textGrob("Total Opportunity Amount", rot = 90) g <- gtable_add_grob(g, LeftAxisText, pp1$t, pp1$l-2) g$widths[2] <- unit.c(unit(1, "grobwidth", LeftAxisText) + unit(1, "line")) # Draw it grid.newpage() grid.draw(g)
这篇关于有没有办法在barplot或ggplot的同一个图上使用barplot和堆叠的barplot?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文