0

I've written a function in R to produce a graph from a given data frame:

my_graph <- function (df, scale_fac)
{

  row_count = nrow(df)

  df %>% mutate(star_sign = as.numeric(factor(star_sign, levels = lvls))) %>%
    ggplot(aes(star_sign)) +
    geom_line(aes(y = mean), color = "red") +
    geom_line(aes(y = min), color = "blue") + 
    geom_line(aes(y = max), color = "green") + 
    geom_col(aes(y = scale_fac * exposure), width = 0.5, fill = "blue") + 
    scale_y_continuous("Linear Predictor", sec.axis = sec_axis(~ ./scale_fac , name = "Exposure")) +
    scale_x_continuous("Star Sign", breaks = c(1:row_count), labels = df$lvls) +
    theme_bw()

}

df <- data.frame(star_sign = c("Aries", "Taurus", "Gemini", "Cancer", "Leo", "Virgo", "Libra", "Scorpio", "Sagittarius", "Capricorn", "Aquarius", "Pisces"),
                 exposure = c(50, 70, 60, 40, 45, 78, 42, 22, 28, 49, 50, 31),
                 mean = c(1.1, 1.2, 1.4, 1.3, 1.8, 1.6, 1.4, 1.3, 1.2, 1.1, 1.5, 1.3))

df$min <- 0.95 * df$mean
df$max <- 1.05 * df$mean

df$lvls = c("Aries", "Taurus", "Gemini", "Cancer", "Leo", "Virgo", "Libra", "Scorpio", "Sagittarius", "Capricorn", "Aquarius", "Pisces")

my_graph(df, 1/150)

However there are some hard coded bits in the ggplot() statement such as exposure, mean, min, max which I'd like to get rid of by passing the names of the fields as additional function parameters, but I can't work out how to do it. I first tried using the [[]] notation, but it didn't work. I then discovered that there's a !! notation in tidyverse but to test this I modified my function definition to include a mean_name parameter and then referred to !!mean_name instead of mean inside the ggplot() statement:

my_graph_2 <- function (df, mean_name, scale_fac)
{
  df %>% mutate(star_sign = as.numeric(factor(star_sign, levels = df$lvls))) %>%
    ggplot(aes(star_sign)) +
    geom_line(aes(y = !!mean_name), color = "red") +
    geom_line(aes(y = min), color = "blue") + 
    geom_line(aes(y = max), color = "green") + 
    geom_col(aes(y = scale_fac * exposure), width = 0.5, fill = "blue") + 
    scale_y_continuous("Linear Predictor", sec.axis = sec_axis(~ ./scale_fac , name = "Exposure")) +
    scale_x_continuous("Star Sign", breaks = c(1:row_count), labels = df$lvls) +
    theme_bw()
}

df <- data.frame(star_sign = c("Aries", "Taurus", "Gemini", "Cancer", "Leo", "Virgo", "Libra", "Scorpio", "Sagittarius", "Capricorn", "Aquarius", "Pisces"),
                 exposure = c(50, 70, 60, 40, 45, 78, 42, 22, 28, 49, 50, 31),
                 mean = c(1.1, 1.2, 1.4, 1.3, 1.8, 1.6, 1.4, 1.3, 1.2, 1.1, 1.5, 1.3))

df$min <- 0.95 * df$mean
df$max <- 1.05 * df$mean

df$lvls = c("Aries", "Taurus", "Gemini", "Cancer", "Leo", "Virgo", "Libra", "Scorpio", "Sagittarius", "Capricorn", "Aquarius", "Pisces")

my_graph_2(df, "mean", 1/150)

When I run this I see:

Error: Discrete value supplied to continuous scale

which I don't understand. Can anyone help please?

Update: if I use aes_string() it seems to work. Revised function definition:

my_graph <- function (df, mean_name, scale_fac)
{
  row_count = nrow(df)

  df %>% mutate(star_sign = as.numeric(factor(star_sign, levels = lvls))) %>%
    ggplot(aes(star_sign)) +
    #geom_line(aes(y = mean), color = "red") +
    geom_line(aes_string(y = mean_name), color = "red") +
    geom_line(aes(y = min), color = "blue") + 
    geom_line(aes(y = max), color = "green") + 
    geom_col(aes(y = scale_fac * exposure), width = 0.5, fill = "blue") + 
    scale_y_continuous("Linear Predictor", sec.axis = sec_axis(~ ./scale_fac , name = "Exposure")) +
    scale_x_continuous("Star Sign", breaks = c(1:row_count), labels = df$lvls) +
    theme_bw()
}
Alan
  • 619
  • 6
  • 19
  • 1
    Can you use `aes_string`? – r2evans Jan 27 '20 at 16:45
  • BTW, should `labels=df$lvls` be just `labels = lvls`? – r2evans Jan 27 '20 at 16:46
  • Thank you. I did try removing the df$ from the labels part but I saw errors sadly. aes_string does seem to work though - have edited my original post above... – Alan Jan 27 '20 at 16:53
  • `!!` isn't for strings, i.e, when you use `!!` I would expect your call to be `my_graph_2(df, mean, 1/150)`, without quotes around `"mean"`. But overall, I think you should read through the [FAQ on this topic](https://stackoverflow.com/a/53168593/903061). It's got several worked examples. – Gregor Thomas Jan 27 '20 at 17:03

0 Answers0