0

I'm trying to create a plot with multiple functions. Each function is defined by coefficients in a data frame, each row of the data frame contains the coefficients for one function and an identifier for the group.

The goal is to have stat_function draw the lines over using coefficients from the data frame, but with no actual data for x. Each line should have a unique colour and be listed in the legend

I have seen examples where several stat_functions are added and the colours are individually defined here. I would like to avoid this to make the function dynamic and be able to plot a variable number of functions with minimal changes.

The answer found here is very close to what I am looking for, however every function has the same colour and there is no legend.

I have managed to output a plot with unique colours and no legend, and with a legend but only one colour.

Here is an example of my plot in ggplot:

library(plyr)

#create data frame

qr <- c(0.11,0.11,0.11,0.05)
qs <- c(0.98,0.98,0.97,0.93)
alpha <- c(78.0564,141.017,58.0405,12.6902)
n <- c(1.53364,1.37685,1.42174,1.15284)
ks <- c(9.936,3.915563,04575,0.312171)
l <- c(-0.09953,-1.5645,-0.12945,2.16382)
m <- 1-1/n
depth <- c(1,2,3,4)

coefs <- data.frame(qr,qs,alpha,n,ks,l,m,depth)

#legend one colour
coeflines1 <-
  alply(as.matrix(coefs), 1, function(coef) {
    stat_function(fun=function(x)
      {coef[1]+(coef[2]-coef[1])/((1+(coef[3]*x)^coef[4])^coef[7])},
      aes(colour = as.factor(depth[1])))
  })

ggplot(data.frame(x=c(0.001, 10)), aes(x=x)) + 
  coeflines1 +
  scale_x_log10()

#no legend multile colour
coeflines2 <-
  alply(as.matrix(coefs), 1, function(coef) {
    stat_function(fun=function(x)
    {coef[1]+(coef[2]-coef[1])/((1+(coef[3]*x)^coef[4])^coef[7])},
    colour = coef[8])
  })

ggplot(data.frame(x=c(0.001, 10)), aes(x=x)) + 
  coeflines2 +
  scale_x_log10()

The problem with the first example is that it is not referencing anything within the functions. If depth[1] is changed to coef[8] I get Error in coef[8] : object of type 'closure' is not subsettable

In the second example no legend appears because I haven't mapped an aesthetic. How can I map an aesthetic that corresponds to the last (8th) column of the data frame coefs?

4
  • What is alply in coeflines1 ? Did you mean apply ? Commented Feb 12, 2018 at 8:47
  • For the second plot, is it coeflines2 instead of coeflines ? Commented Feb 12, 2018 at 8:48
  • Error in coef[8] .. May be you can do it again with coefs intead of coef and see what happens ... Commented Feb 12, 2018 at 8:52
  • alply is from the plyr package, It slices an Array into a List by row (1). Yes you are correct, the second plot should have coeflines2, I've updated the question to reflect this and added the package. Using coefs instead access the entire list instead of position 8 in the array. coefs[[8]][1] could be used to get the first element, however it does not iterate through each row. As such, it gives the error 'x' must be atomic for 'sort.list'. Commented Feb 12, 2018 at 15:34

1 Answer 1

0

One problem that you are running into is that there is a function coef. When you see the complaint about a 'closure', that is why. It is looking at the function, not your argument inside your anonymous function.

Second, when plotting just functions without data, the help for stat_function says to "specify range of x-axis" and gives an example using xlim. Since you already have an x axis specification, you will need to include the limits in that.

The plyr package is rather old (now, recognizing the question was 6 years ago), so I have used function from purrr instead. Also, I cleaned up the data creation code so as to not leave objects lying about that might make it harder to "find" the right ones.

library(tidyverse)

coefs <- 
  data.frame(
    qr = c(0.11,0.11,0.11,0.05),
    qs = c(0.98,0.98,0.97,0.93),
    alpha = c(78.0564,141.017,58.0405,12.6902),
    n = c(1.53364,1.37685,1.42174,1.15284),
    ks = c(9.936,3.915563,04575,0.312171),
    l = c(-0.09953,-1.5645,-0.12945,2.16382),
    m = 1 - 1/c(1.53364,1.37685,1.42174,1.15284),
    depth = c(1,2,3,4))

coeflines1 <-
  pmap(
    .l = coefs, 
    .f = \(qr, qs, alpha, n, ks, l, m, depth) 
      stat_function(
      fun=function(x) {
        qr+(qs-qr)/((1+(alpha*x)^n)^m)
      },
      aes(colour = factor(depth))
      )
  )

ggplot() +
  coeflines1 +
  scale_x_log10(limits = c(0.001, 10))

Plot of multiple functions dependent on a matrix of coefficients using ggplot2

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.