我正在使用sec_axis()
函数创建带有辅助轴的ggplot,但是在保持正确的比例时遇到了麻烦。
以下是可重现的示例
# load package
library(ggplot2)
# produce dummy data
data = data.frame(week = 1:5,
count = c(45, 67, 21, 34, 50),
rate = c(3, 6, 2, 5, 3))
# calculate scale (and save as an object called 'scale')
scale = max(data$count)/10
# produce ggplot
p = ggplot(data, aes(x = week)) +
geom_bar(aes(y = count), stat = "identity") +
geom_point(aes(y = rate*scale)) +
scale_y_continuous(sec.axis = sec_axis(~./scale, name = "% positive",
breaks = seq(0, 10, 2)))
# look at ggplot - all looks good
p
# change the value of the scale object
scale = 2
# look at ggplot - you can see the scale has now change
p
实际上,我在一个循环中生成一系列ggplot,并且在循环的每次迭代中,“ scale”对象都会发生变化
如何确保辅助y轴的比例保持固定? (即使“ scale”对象的值发生了变化)
我想使示例尽可能简单(请参见上面的示例),但根据要求,我将添加一个包含循环的示例
# load package
library(ggplot2)
# produce dummy data
data = data.frame(group = c(rep("A", 5), rep("B", 5)),
week = rep(1:5, 2),
count = c(45, 67, 21, 34, 50,
120, 200, 167, 148, 111),
rate = c(3, 6, 2, 5, 3,
15, 17, 20, 11, 12))
# define the groups i want to loop over
group = c("A", "B")
# initalize an empty list (to store figures)
fig_list = list()
for(i in seq_along(group)){
# subset the data
data.sub = data[data$group == group[i], ]
# calculate scale (and save as an object called 'scale')
scale = max(data.sub$count)/20
# produce the plot
p = ggplot(data.sub, aes(x = week)) +
geom_bar(aes(y = count), stat = "identity") +
geom_point(aes(y = rate*scale), size = 4, colour = "dark red") +
scale_y_continuous(sec.axis = sec_axis(~./scale, name = "% positive",
breaks = seq(0, 20, 5))) +
ggtitle(paste("Plot", group[i]))
# print the plot
print(p)
# store the plot in a list
fig_list[[group[i]]] = p
}
在循环中打印时,我得到以下数字(一切看起来不错)
但是...如果我从创建的列表中调用A组的图形,您会看到次级y轴比例现在不正确(它使用了为B组创建的比例)
fig_list[["A"]]
答案 0 :(得分:1)
感谢您的编辑,这使事情更加清晰。您的问题源于R评估对象的方式。 fig_list
中的图不是图像,而是有关如何生成图的轮廓。它仅在您调用print
(通过键入fig_list["A"]
并按Enter键)时生成。由于scale
的值在整个循环中都会变化,因此,如果稍后评估该图,则将是不正确的,因为它将使用scale
的最后一次迭代。
一个简单的解决方案是将要打印的代码包装在一个函数中并使用lapply
:
make_plot <- function(df) {
scale = max(df$count)/20
ggplot(df, aes(x = week)) +
geom_bar(aes(y = count), stat = "identity") +
geom_point(aes(y = rate*scale), size = 4, colour = "dark red") +
scale_y_continuous(sec.axis = sec_axis(~./scale, name = "% positive",
breaks = seq(0, 20, 5))) +
ggtitle(paste("Plot", unique(df$group)))
}
grouped_data <- split(data, data$group)
fig_list <- lapply(grouped_data, make_plot)
现在,当您调用第一个图时,将对其进行正确评估。
fig_list["A"]
#> $A
当您的环境中碰巧有一个伪造值的对象scale
时,这仍然有效,因为R在函数调用而不是全局环境中查找scale
。
由reprex package(v0.2.0)于2018-09-02创建。