4

I need to generate a plot inside a function, relying on aes_string(), and I need labels as rownames.

The below plot works fine, but not inside a function.

library(ggplot2)
data(mtcars)
plotfun <- function(cars) {
  g <- ggplot(data = cars, aes_string(x = "mpg", y = "disp", label = "rownames(cars)"))
  g <- g + geom_point()
  g <- g + geom_text()
  g
}
plotfun(cars = mtcars)

When run as a function, that gets me:

Error: Aesthetics must either be length one, or the same length as the dataProblems:mpg, disp

I can't wrap my head around it. I am aware that there are plenty of similar questions about aes_string() inside a function –– I just wasn't able to adapt their solutions to my problem.

Ps.: obviously, the above MWE is pretty stupid; in my real use-case, I run the plot through for loops, hence the need for aes_string().

Community
  • 1
  • 1
maxheld
  • 3,963
  • 2
  • 32
  • 51
  • 1
    i would just use the rownames and create a new column and move on – rawr Jul 17 '15 at 21:00
  • yup, thought about that – does not work in my case, because said for loop loops over the *columns* of that df ... so I can't "pollute" it with other columns. Also namespace headaches there. – maxheld Jul 17 '15 at 21:04

2 Answers2

5

I think you would be better served by aes_q here rather than aes_string

library(ggplot2)
data(mtcars)
plotfun <- function(cars) {
  g <- ggplot(data = cars, aes_q(x = as.name("mpg"), y = as.name("disp"), label=rownames(cars)))
  g <- g + geom_point()
  g <- g + geom_text()
  g
}
plotfun(cars = mtcars)

The aes_q allows you to pass unevaluated symbols and calls so we just use as.name() to convert your strings into symbols that can later be evaluated in your data.

MrFlick
  • 195,160
  • 17
  • 277
  • 295
  • fantastic; did not know about `aes_q()`. Seems to be a recent addition, right? It's not on http://docs.ggplot2.org/0.9.3/index.html, but *is* on CRAN already. – maxheld Jul 17 '15 at 21:14
  • @maxheld apparently [since 1.0](https://github.com/hadley/ggplot2/blob/efddff695a7b78ac26666afa994f7db834e6464a/NEWS#L194:L196) – rawr Jul 17 '15 at 21:17
4

Using it inside of deparse seems to work with aes_string:

plotfun <- function(cars) {
  g <- ggplot(data = cars, aes_string(x = "mpg", y = "disp", 
              label = deparse(rownames(cars))))
  g <- g + geom_point()
  g <- g + geom_text()
  g
}

plotfun(cars = mtcars)

enter image description here

For some additional info deparse will turn unevaluated expressions i.e. (rownames(cars)) into character strings which means in case of mtcars:

> deparse(rownames(mtcars))
[1] "c(\"Mazda RX4\", \"Mazda RX4 Wag\", \"Datsun 710\", \"Hornet 4 Drive\", "         
[2] "\"Hornet Sportabout\", \"Valiant\", \"Duster 360\", \"Merc 240D\", \"Merc 230\", "
[3] "\"Merc 280\", \"Merc 280C\", \"Merc 450SE\", \"Merc 450SL\", \"Merc 450SLC\", "   
[4] "\"Cadillac Fleetwood\", \"Lincoln Continental\", \"Chrysler Imperial\", "         
[5] "\"Fiat 128\", \"Honda Civic\", \"Toyota Corolla\", \"Toyota Corona\", "           
[6] "\"Dodge Challenger\", \"AMC Javelin\", \"Camaro Z28\", \"Pontiac Firebird\", "    
[7] "\"Fiat X1-9\", \"Porsche 914-2\", \"Lotus Europa\", \"Ford Pantera L\", "         
[8] "\"Ferrari Dino\", \"Maserati Bora\", \"Volvo 142E\")"   

which as a character vector can be easily evaluated inside of aes_string.

LyzandeR
  • 37,047
  • 12
  • 77
  • 87