我需要在研究中为各种受试者制作大量的药物浓度图,并且我希望根据他们服用的药物一致地设定颜色。但并非所有患者都服用相同的药物。这是我尝试过的:
library(plyr)
library(ggplot2)
library(gridExtra)
A <- data.frame(Time = seq(0, 20, 5),
DrugConcentration = 100*exp(-0.25*seq(0, 20, 5)),
Drug = "Midazolam")
B <- data.frame(Time = rep(seq(0, 20, 5), 2),
DrugConcentration = c(100*exp(-0.25*seq(0, 20, 5)),
75*exp(-0.1*seq(0, 20, 5))),
Drug = rep(c("Midazolam", "Dextromethorphan"), each = 5))
C <- data.frame(Time = rep(seq(0, 20, 5), 3),
DrugConcentration = c(100*exp(-0.25*seq(0, 20, 5)),
75*exp(-0.1*seq(0, 20, 5)),
50*exp(-0.15*seq(0, 20, 5))),
Drug = rep(c("Midazolam", "Dextromethorphan", "Tolbutamide"),
each = 5))
D <- data.frame(Time = rep(seq(0, 20, 5), 2),
DrugConcentration = c(100*exp(-0.25*seq(0, 20, 5)),
50*exp(-0.15*seq(0, 20, 5))),
Drug = rep(c("Midazolam", "Tolbutamide"),
each = 5))
DrugList <- list(A, B, C, D)
MyColors <- data.frame(Drug = c("Midazolam", "Dextromethorphan", "Tolbutamide"),
Color = c("red", "green", "blue"),
stringsAsFactors = FALSE)
PlotList <- list()
for(i in 1:length(DrugList)){
DrugList[[i]] <- arrange(DrugList[[i]], Drug, Time)
MyColors.temp <- join(DrugList[[i]][, c("Drug", "Time")],
MyColors, by = "Drug")
MyColors.temp <- unique(MyColors.temp[, c("Drug", "Color")])
MyColors.temp <- arrange(MyColors.temp, Drug)
PlotList[[i]] <-
ggplot(DrugList[[i]],
aes(x = Time, y = DrugConcentration,
color = Drug)) +
geom_point() + geom_line() +
scale_color_manual(values = MyColors.temp$Color)
}
循环运行,但是当我尝试
时marrangeGrob(PlotList, nrow = 2, ncol = 2)
我收到错误:Insufficient values in manual scale. 3 needed but only 2 provided.
如果我单独查看每个图,例如,通过键入PlotList[[1]]
,前两个图将至少生成图(尽管每种药的颜色不一致)而不是我指定的那个),但第三个是给我一个关于没有足够值的错误的那个。
这里发生了什么?为什么这不起作用?
答案 0 :(得分:1)
为什么这不起作用?
情节3是问题 - 不是单独的,而是与for循环和ggplot2的懒惰评估机制相结合。当您定义每个图时,ggplot2正确捕获第i个数据集的环境,但手动比例存储为未评估的承诺。当它最终被评估时(在绘制之前不久调用ggplot_build),MyColors.temp
只有两个值(循环的最新迭代),而图3抱怨手动缩放提供的值太少。
为什么色标不一致?
scale_colour_manual
需要一个命名向量,而不是一对值 - 中断(在我阅读帮助页面之前,它确实欺骗了我!)。
有一些可能的解决方案。
MyColors <- c("Midazolam" = "red", "Dextromethorphan" = "green", "Tolbutamide" = "blue")
DrugList <- list(A, B, C, D)
PlotList <- list()
for(i in 1:length(DrugList)){
PlotList[[i]] <-
ggplot(arrange(DrugList[[i]], Drug, Time),
aes(x = Time, y = DrugConcentration,
color = Drug)) +
geom_point() + geom_line() +
scale_colour_manual(values = MyColors) +
theme()
}
grid.arrange(grobs=PlotList)
m <- reshape2::melt(DrugList, measure.vars = "DrugConcentration")
str(m)
p <- ggplot(m, aes(x = Time, y = value, color = Drug)) +
facet_wrap(~L1) +
geom_point() + geom_line() +
scale_colour_manual(values = MyColors)
ggforce
似乎提供了可以扩展到多个页面的构面功能。使用额外的虚拟变量将整个数据集拆分成单独的2x2方面也很容易实现。
如果您需要单独的图表,使用长格式data.frame,
也更容易lp <- plyr::dlply(m, "L1", function(d) p %+% d)
grid.arrange(grobs = lp)