Creating a new column/vector of expressions in R

53 Views Asked by At

I have an example dataset:

test <- data.frame(x = c("BG10", "C1456", "DXT6"), y = c("293S", "124F", "124F"))
      x    y
1  BG10 293S
2 C1456 124F
3  DXT6 124F

where I am ultimately trying to combine columns x and y, and then label the new column such that values in x are on top of y for plotting purposes:

test %>% mutate(label = paste(x, y, sep = " "), labels = factor(label, labels = bquote(atop(.(x), .(y)))))

the above will give an error.

I thought of creating a vector of expressions:

test %>% split(.$x) %>% map(~ bquote(atop(.(.$x), .(.$y)))) %>% unlist(use.names = FALSE)
[[1]]
atop("BG10", "293S")

[[2]]
atop("C1456", "124F")

[[3]]
atop("DXT6", "124F")

But it would remove the expressions whenever I tried converting the list to a vector. Are there any suggestions on how to go about this? Thanks in advance!

2

There are 2 best solutions below

0
r2evans On BEST ANSWER

We can Map them into a list-column of expressions.

library(dplyr) # not strictly required ...
out <- test %>%
  mutate(label = Map(function(a, b) bquote(atop(.(a), .(b))), x, y))
out
#       x    y                 label
# 1  BG10 293S  atop("BG10", "293S")
# 2 C1456 124F atop("C1456", "124F")
# 3  DXT6 124F  atop("DXT6", "124F")

We can verify they are expressions ("language") with str:

str(out)
# 'data.frame': 3 obs. of  3 variables:
#  $ x    : chr  "BG10" "C1456" "DXT6"
#  $ y    : chr  "293S" "124F" "124F"
#  $ label:List of 3
#   ..$ BG10 : language atop("BG10", "293S")
#   ..$ C1456: language atop("C1456", "124F")
#   ..$ DXT6 : language atop("DXT6", "124F")

and verify that other tools will treat them as such:

library(ggplot2)
ggplot(out, aes(x, y)) +
  geom_text(aes(label = label), parse = TRUE)

sample ggplot with quoted "atop" text labels

(If you prefer to use purrr, then replace the Map with

pmap(list(x, y), ~ bquote(atop(.(.x), .(.y))))
4
Allan Cameron On

A simple alternative is to just paste the strings together with a newline character:

test$label <- paste(test$x, test$y, sep = '\n')

Giving you

ggplot(test, aes(x, y, label = label)) + geom_text()

enter image description here