3

The idea is to patch a call to ggplot in a function.

The example:

library(dplyr)
library(ggplot2)
library(lazyeval)

df <- data.frame(A=letters[1:10], B=2:11, C=3:12))

func <- function(name, dat=df) {

  output <- dat %>%
    select_(~A,name) %>%
    arrange_(interp(~desc(var), var=as.name(name)))

  plot <- 
    ggplot(output, aes_string(x=reorder(~A,-name), y=B)) +
    geom_bar(stat='identity')

  print(plot)
  return(plot)

}

result <- func("B")

Compiling gives:

Error in -name : invalid argument to unary operator.

I tried deparse and substitute. Not sure I got the right combo. Any ideas?

remi
  • 781
  • 2
  • 13
  • 22
  • I’m not sure what purpose the `reorder` is even supposed to serve here — it seems like you’re attempting to plot `B` against mismatched `A`. That’s not a good idea, and I don’t think ggplot supports it. – Konrad Rudolph Sep 21 '15 at 10:25
  • @@Konrad: see this previous [question](http://stackoverflow.com/questions/32681370/ggplot2-x-axis-ordering-unresolved) for what `reorder` resolves. – remi Sep 21 '15 at 11:11
  • Ah I see, that makes sense. However, the fix for this is straightforward, isn’t it? Simply reorder the factor outside the `ggplot` call. – Konrad Rudolph Sep 21 '15 at 11:47
  • I tried :-) to no avail, so far. Care to share a way to do? Thanks – remi Sep 21 '15 at 12:05
  • Yeah, turned out harder than I thought. Anyway, take a look at my answer. – Konrad Rudolph Sep 21 '15 at 12:07

1 Answers1

7

Reorder the data before passing it to ggplot. The following code also moves some of the column names around in the ggplot call, because otherwise you’d always be plotting A against B, regardless of the name argument — or was that intentional?

function (dat, name) {
    var = as.name(name)
    reord = list(interp(~ reorder(var, -var), var = var))
    output = dat %>%
        select_(~A, name) %>% # Not actually necessary.
        arrange_(interp(~ desc(var), var = var)) %>%
        mutate_(.dots = setNames(reord, name))

    plot = ggplot(output, aes_string(x = 'A', y = name)) +
        geom_bar(stat = 'identity')

    plot(plot)
    plot
}

func(df, 'B')

I’m using the mutate_(.dots = …) form here. Have a look at dplyr’s “NSE” vignette for more information on its usage.

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
  • @@Konrad: the only re-ordering needed is after `output` is obtained to force ggplot to break alphabetical tying when plotting. So far I found this chunk to work: `ggplot(output,aes_string(x=quote(A), y=B) )+...` as in the question. Now, how to do the reordering with reorder?? – remi Sep 21 '15 at 13:37
  • @remi Well, you’d *still* do it as in my answer. – Konrad Rudolph Sep 21 '15 at 13:49
  • @@Konrad: sorry, well it actually doesn't produce the needed outcome. I think it is the call `mutate_` that messes things. Basically, we have to make `dat$A <- reorder(dat$A, -dat$name)` executable in the local env. just before calling ggplot. – remi Sep 21 '15 at 22:22
  • 1
    @remi Do you actually want to reorder `A` rather than what ever `name` is? If so, the code is easily adapted, just change the `mutate_` statement to `mutate_(A = interp(~ reorder(A, -var), var = var))`. – Konrad Rudolph Sep 21 '15 at 23:14