保持ggplot辅助轴刻度固定

时间:2018-09-01 14:28:25

标签: r ggplot2

我正在使用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

}

在循环中打印时,我得到以下数字(一切看起来不错)

loop_print_A

loop_print_B

但是...如果我从创建的列表中调用A组的图形,您会看到次级y轴比例现在不正确(它使用了为B组创建的比例)

fig_list[["A"]]

enter image description here

1 个答案:

答案 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创建。