【问题标题】:How to plot bars and one line on two Y-axes in the same chart, with R-ggplot?如何使用 R-ggplot 在同一图表中的两个 Y 轴上绘制条形图和一条线?
【发布时间】:2014-05-07 06:03:18
【问题描述】:

如何在一个折线图下方绘制分组条?

该图可以将分类实验的性能(例如准确性)显示为线(较粗然后标准)。使用左侧 Y 刻度,0 < Accuracy < 1 之间的变化,带有以下文本:“这是准确度”。

然后特征的数量(例如用于文本分类),可以用条形表示。右 Y 轴,0 < NOoFeatures < max(featuresX) 之间的变化,文本:“特征数量”。 X-scale,文本“每个实验使用的特征”。

实际上有四类文本特征可以表示为堆叠(会很好)或分组(首选)条。如果现在一切都以灰度色调显示,那就完美了;)

## Mock-up data:
performanceExps <- c(0.4, 0.5, 0.65, 0.9) # Accuracy
FeaturesExp1 <- c(featuresA=1000, featuresB=0, featuresC=0, featuresD=0) # Used features Experiment 1
FeaturesExp2 <- c(featuresA=1000, featuresB=5000, featuresC=0, featuresD=0) # Used features Experiment 2
FeaturesExp3 <- c(featuresA=1000, featuresB=5000, featuresC=10000, featuresD=0) # Used features Experiment 3
FeaturesExp4 <- c(featuresA=1000, featuresB=5000, featuresC=10000, featuresD=20000) # Used features Experiment 4

Kohske 提供(下)一个非常相似的示例,但我无法使其适应我的问题(使用条形图)。

library(ggplot2)
library(gtable)
library(grid)

grid.newpage()

# two plots
p1 <- ggplot(mtcars, aes(mpg, disp)) + geom_line(colour = "blue") + theme_bw()
p2 <- ggplot(mtcars, aes(mpg, drat)) + geom_line(colour = "red") + theme_bw() %+replace% 
  theme(panel.background = element_rect(fill = NA))

# extract gtable
g1 <- ggplot_gtable(ggplot_build(p1))
g2 <- ggplot_gtable(ggplot_build(p2))

# overlap the panel of 2nd plot on that of 1st plot
pp <- c(subset(g1$layout, name == "panel", se = t:r))
g <- gtable_add_grob(g1, g2$grobs[[which(g2$layout$name == "panel")]], pp$t, 
                     pp$l, pp$b, pp$l)

# axis tweaks
ia <- which(g2$layout$name == "axis-l")
ga <- g2$grobs[[ia]]
ax <- ga$children[[2]]
ax$widths <- rev(ax$widths)
ax$grobs <- rev(ax$grobs)
ax$grobs[[1]]$x <- ax$grobs[[1]]$x - unit(1, "npc") + unit(0.15, "cm")
g <- gtable_add_cols(g, g2$widths[g2$layout[ia, ]$l], length(g$widths) - 1)
g <- gtable_add_grob(g, ax, pp$t, length(g$widths) - 1, pp$b)

grid.draw(g)

问题到此结束——这是hrbmstr的代码(谢谢!)

featPerf <- data.frame( expS=c("1", "2", "3", "4"),
                        Experiment1=c(1000, 0, 0, 0),
                        Experiment2=c(1000, 5000, 0, 0),
                        Experiment3=c(1000, 5000, 10000, 0),
                        Experiment4=c(1000, 5000, 10000,20000),
                        accuracy=c(0.4, 0.5, 0.65, 0.9) )

# make room for both axes ; adjust as necessary
par(mar=c(5, 12, 6, 7) + 0.4) 

# plot the bars first with no annotations and specify limits for y
#barplot(as.matrix(featPerf[,2:5]), axes=FALSE, xlab="", ylab="", ylim=c(0, max(colSums(featPerf[2:5]))))
barplot(as.matrix(featPerf[,2:5]), axes=FALSE, xlab="", ylab="", beside=TRUE)

# make the bounding box (or not...it might not make sense for your plot)
#box()

# now make the left axis
axis(2, ylim=c(0, max(colSums(featPerf[2:5]))), col="black", las=1)

# start a new plot
par(new=TRUE)

# plot the line; adjust lwd as necessary
plot(x=1:4, y=featPerf[,6], xlab="Experiments", ylab="", axes=FALSE, type="l", ylim=c(0,1), lwd=5)

# annotate the second axis
axis(4, ylim=c(0,1), col="black", col.axis="black", las=1)
#axis(4, ylim=c(0,1), col="black", col.axis="black", las=1, labels="Accuracy", at = .5, side=3)

#title("An Example of Creative Axes", xlab="X values", ylab="Y=X")
mtext("Accuracy", side=4, line=3, cex.lab=1,las=2, col="black")
mtext("No. of features    ", side=2, line=3, cex.lab=1,las=2, col="black")

【问题讨论】:

  • 你的数据是什么,至少是你想要的样子的模型,除了粘贴那个 RPubs 样本之外,你到目前为止还尝试过什么?
  • @hrbrmstr 谢谢 :) 我在上面的描述中添加了模型数据。

标签: r plot ggplot2


【解决方案1】:

感谢您发布数据样本!我认为这就是你想要的。 CAVEAT:我鼓励您并排而不是叠加地块,因为在谈到双轴地块时,我坚定地支持Few [PDF] 阵营。 原因 ggplot2 很难做到这一点。为此,如果您愿意使用基本图形,那非常简单。

# make a data frame for convenience 

featPerf <- data.frame( exp=c("1", "2", "3", "4"),
                        A=c(1000, 1000, 1000, 1000),
                        B=c(0, 5000, 5000, 5000),
                        C=c(1000, 5000, 10000, 0),
                        D=c(1000, 5000, 10000 ,20000),
                        accuracy=c(0.4, 0.5, 0.65, 0.9) )

# make room for both axes ; adjust as necessary
par(mar=c(5, 5, 5, 7) + 0.2) 

# plot the bars first with no annotations and specify limits for y
barplot(as.matrix(featPerf[,2:5]), axes=FALSE, xlab="", ylab="", ylim=c(0, max(colSums(featPerf[2:5]))))

# make the bounding box (or not...it might not make sense for your plot)
box()

# now make the left axis
axis(2, ylim=c(0, max(colSums(featPerf[2:5]))), col="black", las=1)

# start a new plot
par(new=TRUE)

# plot the line; adjust lwd as necessary
plot(x=1:4, y=featPerf[,6], xlab="", ylab="", axes=FALSE, type="l", ylim=c(0,1), lwd=5)

# annotate the second axis
axis(4, ylim=c(0,1), col="black", col.axis="black", las=1)

您可以根据需要调整或添加注释/边距/颜色。我已经造成了足够的伤害:-)

【讨论】:

  • 谢谢,非常好!是否可以将列分组。此外,我在我的问题下方添加了您改编的代码,以展示我如何想象堆叠的列。很多时候我并不像我希望的那样精确(对不起!)。感谢您的耐心:-|
  • 您好,谢谢!我实现了变化(见上面的评论)。请检查并在我的问题下方添加代码,以回答最初的问题(堆叠、分组)。由于我是新手,如果您能抽出一点时间,如果您更改代码以避免列缩放与 ylab 文本崩溃,并在 y-skale 之间添加一个基本图例,我将不胜感激线和条(这在技术上是否可行),没有边界。十分感谢。我将在星期一提交我的论文,我需要几个小时才能找到它。
  • 观察到另一个问题。如果在右侧添加labels="Accuraces",我会收到一个有线错误'labels' is supplied and not 'at',谢谢。
  • @hrbmstr 轴名称已解决。图例没有解决(是否可以制作一个包括条形和线的图例?--没有边界)。代码在我的问题下方。最美好的祝愿
【解决方案2】:

通过调整 Kohske 的示例来解决。这导致与 hrbrmstr 的解决方案相似的情节 - 完全同意重新考虑情节。

library(ggplot2)
library(gtable)
library(reshape2)

# Data
featPerf <- data.frame( exp=c("1", "2", "3", "4"),
                    A=c(1000, 1000, 1000, 1000),
                    B=c(0, 5000, 5000, 5000),
                    C=c(1000, 5000, 10000, 0),
                    D=c(1000, 5000, 10000 ,20000),
                    accuracy=c(0.4, 0.5, 0.65, 0.9) )

# Barplot ------------------------------------------------
# Reshape data for barplot
df.m <- melt(featPerf[-6])

# Labels for barplot
df.m$barlab <- factor(paste("Experiment", df.m$exp) )

p1 <- ggplot(df.m , aes(x=barlab, y=value, fill=variable)) + 
           geom_bar( stat="identity", position="dodge") +
           scale_fill_grey(start =.1, end = .7 ) +
           xlab("Experiments") + 
           ylab("Number of Labels") + 
           theme(legend.position="top")
g1 <- ggplotGrob(p1)

# Lineplot ------------------------------------------------
p2 <- ggplot(featPerf , aes(x=exp, y=accuracy, group=1)) + geom_line(size=2)  + 
            scale_y_continuous(limits=c(0,1)) + 
            ylab("Accuracy") +
            theme(panel.background = element_rect(fill = NA),
                  panel.grid.major = element_blank(), 
                  panel.grid.minor = element_blank())
g2 <- ggplotGrob(p2)


# Add plots together
pp <- c(subset(g1$layout, name == "panel", se = t:r))
g <- gtable_add_grob(g1, g2$grobs[[which(g2$layout$name == "panel")]], pp$t, 
                 pp$l, pp$b, pp$l)


# Add second axis for accuracy
ia <- which(g2$layout$name == "axis-l")
ga <- g2$grobs[[ia]]
ax <- ga$children[[2]]
ax$widths <- rev(ax$widths)
ax$grobs <- rev(ax$grobs)
ax$grobs[[1]]$x <- ax$grobs[[1]]$x - unit(1, "npc") + unit(0.15, "cm")
g <- gtable_add_cols(g, g2$widths[g2$layout[ia, ]$l], length(g$widths) - 1)
g <- gtable_add_grob(g, ax, pp$t, length(g$widths) - 1, pp$b)


# Add second y-axis title 
ia <- which(g2$layout$name == "ylab")
ax <- g2$grobs[[ia]]
# str(ax) # you can change features (size, colour etc for these - 
# change rotation below 
ax$rot <- 270
g <- gtable_add_cols(g, g2$widths[g2$layout[ia, ]$l], length(g$widths) - 1)
g <- gtable_add_grob(g, ax, pp$t, length(g$widths) - 1, pp$b)

grid.draw(g)

【讨论】:

  • 它有效 :) 太棒了!谢谢你。你很棒。但是是否可以在ggplot p1 之后设置灰度+ scale_fill_grey(start =.1, end = .7)(有效),添加比例xLabels &lt;- c("Experiment1", "Experiment2", "Experiment3", "Experiment4")(无效),xName="Experiments"(无效),yLeftName="Number of Labels"yRightName="Accuracy"`(无效)。
  • 该图显示了我的实验中使用的不同(附加)特征对准确性的影响。如果您想查看完美的非 ggplot(除了缺少的图例),请使用我的问题下方的代码。谢谢你:)
  • @alex;更新了 - 仍有一些事情需要调整 - 玩得开心。
  • 谢谢!这太棒了!祝你有美好的一天:)
  • @alex 你有没有想过如何为第二个 y 轴添加图例?
猜你喜欢
  • 1970-01-01
  • 2015-09-01
  • 2019-03-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-29
  • 1970-01-01
相关资源
最近更新 更多