尝试在 中实现此功能时的基本问题ggvis
是没有position = dodge
像 in 那样的选项ggplot2
,因此不同supp
值的箱线图不能绘制在同一x
坐标处。所以索引x
轴as.factor(dose)
似乎不是一个选择。但是,我们可以做的是使用长度等于唯一剂量值个数的整数索引,然后根据值手动x
将数据的位置向左或向右偏移supp
:
library(ggvis)
library(dplyr)
d <- ToothGrowth
d$xpos <- as.integer(factor(d$dose)) + ifelse(d$supp == "OJ", -.2, .2)
所以我们现在可以使用x = ~xpos
在正确的位置绘制箱线图。下一步是定义包含用于绘制由线连接的点的方法的数据。
means <- d %>% group_by(dose, supp) %>% summarise(len = mean(len))
means$xpos <- as.integer(factor(means$dose))
means <- group_by(means, supp) # The grouping is needed for layer_paths()
该图现在可以得到
ggvis(d, x = ~xpos, y = ~len, stroke = ~supp) %>%
layer_boxplots() %>%
layer_points(data = means, fill := "blue") %>%
layer_paths(data = means)
现在我们遇到的问题是x
图的位置将位于 1、2、3 而不是实际剂量值。这不是很容易克服,因为add_axis()
无法重新标记轴刻度(此外,我们不能首先使用实际剂量值而不是 1、2、3,因为这会将箱线图放置在剂量值 0.5 和 1 比剂量值 1 和 2 的剂量值更接近)。这可以通过一个不那么优雅的技巧来克服,即为每个单剂量值添加一个轴。该函数add_axis()
提供了一种修改轴属性(包括标签)的方法,但它将对整个轴使用相同的标签,因为属性适用于整个轴。因此,通过为每个剂量值添加一个轴,我们可以一个一个地操作标签。这看起来像
ggvis(d, x = ~xpos, y = ~len, stroke = ~supp) %>%
layer_boxplots() %>%
layer_points(data = means, fill := "blue") %>%
layer_paths(data = means) %>%
add_axis("x", title = "Dose",
values = c(1, 1), # For some reason values of length 1 don't work...
properties = axis_props(labels = list(text = "0.5"))) %>%
add_axis("x", title = "",
values = c(2, 2),
properties = axis_props(labels = list(text = "1"))) %>%
add_axis("x", title = "",
values = c(3, 3),
properties = axis_props(labels = list(text = "2"))) %>%
add_axis("y", title = "Response")
或者,您可以为这些使用循环,这样您就不必一遍又一遍地键入相同的内容
labs <- data.frame(dose = unique(d$dose))
labs$xpos <- as.integer(factor(labs$dose))
v <- ggvis(d, x = ~xpos, y = ~len, stroke = ~supp) %>%
layer_boxplots() %>%
layer_points(data = means, fill := "blue") %>%
layer_paths(data = means) %>%
add_axis("x", title = "Dose", ticks = 0) %>%
add_axis("y", title = "Response")
for (i in 1:nrow(labs)) {
v <- add_axis(v, "x", title = "", values = rep(labs[i, "xpos"], 2),
properties = axis_props(labels = list(text = as.character(labs[i, "dose"]))))
}
最后的结果是这样的