可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
Suppose I want to plot an R function:
weibull <- function(ALPHA, LAMBDA, T){
ALPHA*LAMBDA*(T^(ALPHA-1))
}
So the function takes the arguments alpha, lambda and T. I want to generate a plot where in one plot alpha =0.5, time ranges from 0 to 2 and lambda=1, 2, 4, 8, 16 and in another, alpha=1, time ranges from 0 to 2 and lambda=1, 2, 4, 8, 16.
In the past for plotting functions with just one argument, I've used curve and then done ADD=TRUE if I wanted another curve on the same plot. So for instance, in the past I've used:
lambda <- 0.5
pdf <- function(x){
lambda*exp(-lambda*x)
}
survival <- function(x){
exp(-lambda*x)
}
plot(curve(pdf, 0, 6), type="l", ylim=c(0, 1), lwd=3, ylab="", xlab="", xaxs="i", yaxs="i", main=expression(paste("Exponential Distribution ", lambda, "=0.5")), cex.main=2, cex.axis=2, cex.lab=2)
curve(survival, 0, 6, add=TRUE, col="plum4", lwd=3)
But in this example the functions just have one argument, which is x. Whereas, now I want to vary LAMBDA, T and ALPHA. The curve function does not work and I am not sure how else to approach this.
回答1:
I'd do it with plyr and ggplot2,
weibull <- function(alpha, lambda, time){
data.frame(time = time, value = alpha*lambda*(time^(alpha-1)))
}
library(plyr)
library(ggplot2)
params <- expand.grid(lambda = c(1, 2, 4, 8, 16), alpha = c(0.5, 1))
all <- mdply(params, weibull, time = seq(0, 2, length=100))
ggplot(all, aes(time, value, colour=factor(lambda)))+
facet_wrap(~alpha,scales="free", ncol=2) + geom_line()
回答2:
If you use curve
, you can specify an expression with a free variable x
that will get replaced by the range of values specified in your from=
/to=
parameters. For example you can do
weibull <- function(ALPHA, LAMBDA, T){
ALPHA*LAMBDA*(T^(ALPHA-1))
}
lambda<-c(1, 2, 4, 8, 16)
col<-rainbow(length(lambda))
layout(matrix(1:2, nrow=1))
for(i in seq_along(lambda)) {
curve(weibull(.5, lambda[i], x), from=0, to=2, add=i!=1, col=col[i], ylim=c(0,50), main="alpha=.5")
}
legend(1,50,lambda, col=col, lty=1)
for(i in seq_along(lambda)) {
curve(weibull(1, lambda[i], x), from=0, to=2, add=i!=1, col=col[i], ylim=c(0,20), main="alpha=1")
}
which will produce a plot like
回答3:
A tidyverse alternative,
weibull <- function(alpha, lambda, time){
data.frame(time = time, value = alpha*lambda*(time^(alpha-1)))
}
library(ggplot2)
library(tidyverse)
params <- tidyr::crossing(lambda = c(1, 2, 4, 8, 16), alpha = c(0.5, 1))
params %>%
dplyr::mutate(purrr::pmap(., .f = weibull, time = seq(0, 2, length=100))) %>%
tidyr::unnest() %>%
ggplot(aes(time, value, colour=factor(lambda)))+
facet_wrap(~alpha,scales="free", ncol=2) + geom_line()
回答4:
This is similar to MrFlick's answer but shorter:
par(mfrow=1:2)
lapply(0:4, function(l) curve(weibull(0.5, 2^l, x), col=l+1, add=l!=0, ylim=c(0,50), xlim=c(0,2)))
lapply(0:4, function(l) curve(weibull(1, 2^l, x), col=l+1, add=l!=0, ylim=c(0,50), xlim=c(0,2)))
Ok if you're a big fan of nested lapply
's you can also do:
lapply(c(0.5,1), function(a) lapply(0:4, function(l) curve(weibull(a, 2^l, x), col=l+1, add=l!=0, ylim=c(0,50), xlim=c(0,2))))