ggplot2 plot function with several arguments

2019-06-05 03:40发布

I got this function.

change <- function(score, d, k, p) {k*(score - 1/(1+k^(d/p)))}

I would like to plot, in one single plot, all results of this function for a range of arguments d and p. In base r it would be this.

parameters <- c(100:400)
colorshelf <-rainbow(length(parameters)) #red is low
for(i in seq_along(parameters)) {
    print(i)
    curve(change(score=1, d=x, k=100, p=parameters[i]), from=0, to=500, add=T, col=colorshelf[i])
}

But I thought this must be possible in ggplot2, but can not wrap my head around this. I am currently stuck with this. Any help is appreciated.

ggp <- ggplot(data.frame(Ds=c(0:1000), Ps=c(0:1000)), aes(x=Ds, col=Ps)) + 
    stat_function(fun=change, args=list(score=1, d=Ds, k=100, p=Ps))
ggp

标签: r plot ggplot2
2条回答
等我变得足够好
2楼-- · 2019-06-05 03:40

I would do this outside of ggplot2. I think it might be too much to expect ggplot to vectorise over two different parameters ...

This is with tidyverse, but could easily be done with apply as well.

 library(dplyr)
 change <- function(score, d, k, p) {k*(score - 1/(1+k^(d/p)))}
 dd <- expand.grid(d=0:1000,p=0:100)
 dd %>% rowwise %>%
     mutate(c=change(score=1,d=d,k=100,p=p)) ->
  dd2

 library(ggplot2)
 ggp <- ggplot(dd2,aes(d,c,col=p,group=p))+
            geom_path()

I only did p from 0 to 100 (rather than 0 to 1000) because 1 million points is a fairly large data set for ggplot. (Do you really need to see 1000 separate values? Maybe seq(0,1000,length=100) ?

查看更多
相关推荐>>
3楼-- · 2019-06-05 03:56

just now, i had a very similar problem; i wanted to plot a function in ggplot with multiple parameters stored rowwise in a dataframe. As i did not need the dataframe with the function evaluated for each data point in the remainder of my code, i let ggplot do the dirty work for me. However, my approach comes at the minor disadvantage of positional knowlege on the dataframes ordering in apply (which should not be your problem). Also i need a color column (here: 'group'), which was in my case actually desirable for grouping. And ever since your parameters are unbalnced, you will have to expand.grid the parameters

The skeleton of the solution i came up with is basically the following:

p = ggplot(data.frame(x = c(-5, 10)), aes(x)) 
# this format specifies start & end of the x-axis for which the function is evaluated. 
d = data.frame(mu = 1:4, sigma= c(1,1,2,2), group = c(1,1,2,2))
# each row is a parameter set.
p = p + apply(
  d,
  MARGIN = 1,
  FUN = function(z)
    stat_function(
      fun = dnorm, # you can specify your own function which lives in .GlobalEnvir
      geom = "line",
      args = list(mean = z[1] , sd = z[2]),
      color = z[3]
    )
)
print(p)

But if you would have a non-standardized set of parameters (e.g. sometimes you dont have values for mean or sd and would want to omit them entirely in the passing of args) a more flexible approach with lapply might be an alternative. Note, that if you would like to use a default value of the function e.g. dnorm, you do not need to specify the particular parameter.

查看更多
登录 后发表回答