Masoud
Masoud

Reputation: 595

Using ggplot to draw a density function for various values of parameters

I am trying to plot a density function for various values of two parameters as follows:

f_bdsn<-function(x){
  2*(1+delta1*x^2)*dnorm(x)*pnorm(alpha1*x)/(1+delta1)
  }
alpha1<<-0
alpha1<<-0
group1=paste("alpha=",alpha1,", delta=",delta1)
p9 <- ggplot(data.frame(x = c(-4, 4)), aes(x = x)) +
  stat_function(fun = f_bdsn, aes(colour = group1)) 
alpha1<<-0
delta1<<-6
group2=paste("alpha=",alpha1,", delta=",delta1)
p9 <-p9 + stat_function(fun = f_bdsn,
                    aes(colour = group2)) 
p9

I am confused why it does not work! It only draws the function for last values of the parameters.

Upvotes: 0

Views: 84

Answers (2)

MrFlick
MrFlick

Reputation: 206232

The problem is that the parameter values of ggplot for the most part are lazily evaulated. The values aren't actually evaluated until the plot is drawn. Since your function uses global variables, those values aren't resolved till plot time and at the time of the plot they will only have one value, not two different values. You can change this by creating a function generator. For example

f_gen <- function(alpha1, delta1) {
  force(c(alpha1, delta1))
  function(x){
    2*(1+delta1*x^2)*dnorm(x)*pnorm(alpha1*x)/(1+delta1)
}}
alpha1 <- 0
delta1 <- 0
group1 <- paste("alpha=",alpha1,", delta=",delta1)
p9 <- ggplot(data.frame(x = c(-4, 4)), aes(x = x)) +
  stat_function(fun = f_gen(alpha1,delta1), aes(colour = group1)) 
alpha1 <- 0
delta1 <- 6
group2 <- paste("alpha=",alpha1,", delta=",delta1)
p9 <- p9 + 
  stat_function(fun = f_gen(alpha1,delta1), aes(colour = group2)) 
p9

Here fgen is a function that returns a function with the parameters you desire. You might even simplify that to

f_gen <- function(alpha1, delta1) {
  force(c(alpha1, delta1))
  function(x){
    2*(1+delta1*x^2)*dnorm(x)*pnorm(alpha1*x)/(1+delta1)
  }}
gname <- function(alpha1, delta1) paste("alpha=",alpha1,", delta=",delta1)

ggplot(data.frame(x = c(-4, 4)), aes(x = x)) +
  stat_function(fun = f_gen(0,0), aes(colour = gname(0,0))) + 
  stat_function(fun = f_gen(0,6), aes(colour = gname(0,6))) +
  labs(color="Params")

Upvotes: 1

Jamie_B
Jamie_B

Reputation: 299

I've had to make some changes to your original function. Basically, the alpha and delta values need to be parameterised and passed into when calling the function. Then using a for loop we can create as many groups as we want.

# Create Function which takes in an x value, a delta value and an alpha value
f_bdsn<-function(x, delta_input, alpha_input){
  2*(1+delta_input*x^2)*dnorm(x)*pnorm(alpha_input*x)/(1+delta_input)
}

# Define the number of groups, alpha values and delta values
# Note the length of both alpha_values and delta_values are the same
n_groups <- 2
alpha_values <- c(0, 10)
delta_values <- c(6, 16)

# Create inital plot
plot <- ggplot(data.frame(x = c(-4, 4)), aes(x = x))

# Create a for loop to through each group
for (i in seq_len(n_groups)) {
  # Define the group name
  group_name <- paste("alpha=", alpha_values[i],", delta=", delta_values[i])
  
  # Add the values to the main plot variable
  plot <- plot + 
    stat_function(fun = f_bdsn, args = list(delta_input = delta_values[i],
                                            alpha_input = alpha_values[i]),
                  aes(colour = group_name))
}

# Print Plot
plot

Upvotes: 2

Related Questions