5

I am using the dot function to format text labels in a plot created with ggplot2. This works fine when using aes, but doesn't work like expected when using aes_string. Is there a workaround to make it work with aes_string?

require(ggplot2)

# Define the format function
dot <- function(x, ...) { 
  format(x, ..., big.mark = ".", scientific = FALSE, trim = TRUE)
}

# Create dummy data
df <- data.frame(cbind(levels(iris$Species),c(10000000000,200000,30000)))
df$X2 <- as.numeric(as.character(df$X2))

# Works with aes   
ggplot(iris) + 
  geom_bar(aes(Species,Sepal.Width),stat="identity") +     
  geom_text(data=df,aes(x=factor(X1),y=180,label=dot(X2)))


# Doesn't work with aes_string
ggplot(iris) + 
  geom_bar(aes(Species,Sepal.Width),stat="identity") +
  geom_text(data=df,aes_string(x="X1",y=180,label=dot("X2")))
Anders Ellern Bilgrau
  • 9,928
  • 1
  • 30
  • 37
Jonas Tundo
  • 6,137
  • 2
  • 35
  • 45
  • 1
    I think the easiest thing would be to simply apply `dot` outside of ggplot, creating a new column. – joran Jun 18 '14 at 18:50

3 Answers3

3

You're passing a string constant to dot and dot("X2") returns "X2". So you're basically giving aes_string the argument label = "X2".

I got this to work

ggplot(iris) + 
  geom_bar(aes(Species, Sepal.Width), stat = "identity") + 
  geom_text(data=df, aes_string(x="X1", y =180, label = deparse(dot(df$X2))))

Imgur

Edit

As suggested by MrFlick, you could also use df[,"X2"] if you need to pass the column name as a string. I.e.

ggplot(iris) + 
  geom_bar(aes(Species, Sepal.Width), stat = "identity") + 
  geom_text(data=df, aes_string(x="X1", y =180, label = deparse(dot(df[,"X2"]))))
Anders Ellern Bilgrau
  • 9,928
  • 1
  • 30
  • 37
  • In order to specify "X2" as a string, you could use `aes_string(x="X1", y =180, label = deparse(dot(df[,"X2"]))))` – MrFlick Jun 18 '14 at 18:59
3

Rather than just quote "X2", you must quote the whole expression

ggplot(iris) + 
  geom_bar(aes(Species, Sepal.Width), stat = "identity") + 
  geom_text(data=df, aes_string(x="X1", y =180, label = "dot(X2)"))

If you wanted to specify variable names via a character vector, you would use paste() to build that expression.

MrFlick
  • 195,160
  • 17
  • 277
  • 295
2

As implied by my comment, I dislike relying on deparse or other evaluation tricks unless I have to:

col <- "X2"
new_col <- paste0(col,"_dot")
df[,new_col] <- dot(df[,col])
ggplot(iris) + 
    geom_bar(aes(Species,Sepal.Width),stat="identity") + 
    geom_text(data=df,aes_string(x="X1",y=180,label=new_col))

I presented this version as if we were writing code in a function and had received the "X2" as an argument.

joran
  • 169,992
  • 32
  • 429
  • 468