Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ggplot2's aes_string() does not like "rownames(mtcars)" when inside a function

Tags:

r

ggplot2

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().

like image 910
maxheld Avatar asked Jan 07 '23 23:01

maxheld


2 Answers

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.

like image 159
MrFlick Avatar answered Jan 22 '23 22:01

MrFlick


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.

like image 45
LyzandeR Avatar answered Jan 22 '23 22:01

LyzandeR