0

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!

vizidea
  • 153
  • 7

2 Answers2

4

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))))
r2evans
  • 141,215
  • 6
  • 77
  • 149
4

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

Allan Cameron
  • 147,086
  • 7
  • 49
  • 87
  • 1
    Simple. I thought about going this route too, but wondered if `atop(..)` was really a placeholder for more `plotmath` expressions that may not be resolved as quickly with an embedded newline. Nice though! – r2evans Jul 11 '23 at 20:28
  • 1
    @r2evans I thought from the OP that this was the ultimate goal. However, the green tick suggests you were indeed closer to the mark, and your answer is certainly more generally useful. – Allan Cameron Jul 11 '23 at 20:34
  • 1
    Or it could have been that my answer accrued one more up-vote at the time of acceptance, and peer-pressure led them to accept mine instead. Shrug. Interpretation of social norms is a funny thing. – r2evans Jul 11 '23 at 20:36
  • I appreciate both answers! My actual data + plot requires more plotmath expressions, which is why I kept the `atop` placeholder. Thank you both! – vizidea Jul 11 '23 at 22:07