1

I am trying to have subscripts in my geom_label. e.g.

Maine
Apo (km/h) = 9
Qt (m/s) = 90


I am aware of using [x] to get subscripts but I am not sure how to achieve that when I want to get the label values (partly) from a column. I tried using tidyeval (!!) to no avail. Even simply changing parse = T gives me errors. It could be something rudimentary that I am overlooking, but after reading this thread using plotmath in ggrepel labels, I am not sure if it is as simple as I thought.

Here is with what I have so far. I provided the packages and the data I have used, along with data cleaning/preparation steps. Finally, I've shown the code that I have used for creating the "preliminary" plot.

library(tidyverse)
library(stringr)
library(usmap)
library(ggrepel)
library(rlang)
read.table(text = "State     Apo    Qt
NJ  1     10
MO  2     20
SD  3     30
NY  4     40
FL  5     50
OK  6     60
NE  7     70
KY  8     80
ME  9     90
CA  10  100
NC  11  110
MA  12  120
CT  13  140", header = T, stringsAsFactor = F) -> ex1
# get the states full names
region <- state.name[match(ex1$State,state.abb)]
region <- str_to_title(region)

# US map data (50 States)
us1 <- usmap::us_map()

# adding full names to the dataset
ex_df <- cbind(region = region, ex1)

# adding dataset values to the map data (only states with data)
us_val1 <- left_join(ex_df, us1, by = c("region" = "full")) 

# full map dataset joined by ex1 dataset to draw the map
us_map1 <- left_join(us1, ex_df, by = c("full" ="region")) %>% 
           mutate(qQt = replace_na(Qt, 0))

# creating a dataset with centroids of the states (only the ones in ex1)
us_centroids1 <- 
  us_val1 %>%
  group_by(region) %>% 
  summarise(centroid.x = mean(range(x)), 
            centroid.y = mean(range(y)),
            label = unique(State),
            `Apo` = unique(Apo),
            `Qt` = unique(Qt))
## drawing the plot
ggplot() + 
  geom_polygon(data = us_map1, 
               aes(x,y, group = group, fill = Qt), 
               color = "black",
               size = .1) +
  geom_label_repel(data = us_centroids1, 
                   aes(centroid.x, centroid.y, 
                       label = paste(region, "\n Apo (km/h) = ", `Apo`,  "\n Qt (m/s) =", `Qt`)),
                   size = 5/14*8,
                   box.padding = 1,
                   parse = F) +
  scale_fill_gradientn(name = expression(Q[t]~(m/s)),
                       breaks = c(0, seq(10,130,20)),
                       labels = c("", seq(10,130,20)),
                       limits = c(0, 130),
                       colors = c("#DCDCDC", "lightblue", "green"),
                       guide = guide_colorbar(barwidth = 0.8, barheight = 18)) +
  
  theme_void()

M--
  • 25,431
  • 8
  • 61
  • 93
  • Your working minimal working example is not-so-minimal, so it's somewhat involved to see what's going on. Can't you just pre-compute the label values like this https://stackoverflow.com/questions/72961962/r-programmatically-changing-ggplot-scale-labels-to-greek-letters-with-expressio – socialscientist Jul 31 '22 at 03:12
  • @socialscientist it's fairly minimal, I guess I can take out the `scale_fill_...` out or just use random x and y datapoints instead of creating a map but that would just make the plot look crude. Considering the comments I provided, I don't see it very complicated. About your suggestion, I have tried that route before. If I mutate a new column and try `parse = T` I get the following error ```Error in parse(text = text[[i]]) : :1:5: unexpected symbol 1: New Jersey ^``` and I cannot use `label_parse` since these are not axis labels. – M-- Jul 31 '22 at 04:04
  • Please add the example of the above. label_parse works for non-axis labels as well. – socialscientist Jul 31 '22 at 05:45
  • @socialscientist adding every variation that I've tried would clutter the question, if you can post a working solution with label_parse, that'd be appreciated. Although I cannot see how's that possible and doubt that you're onto something. Read the answer below to see why it's more complicated than just creating the labels beforehand. Cheers. – M-- Jul 31 '22 at 14:02
  • It would be possible to construct this plotmath expression as a string. You could use string interpolation with glue, which would remove the need to use `pmap()`, but then you would have to parse it. I neither approach is substantially less complex than the other – shs Jul 31 '22 at 21:21
  • The biggest downside of putting code in a string though, is that you loose the benefits of syntax highlighting, which is why I don't like it and did not use it – shs Jul 31 '22 at 21:28

1 Answers1

1

This is kind of a pain, since plotmath doesn't appear to have line breaks. Thus, you have to work around it with atop(). Use bquote() to insert variable values into the expression. This only works on one element at once, thus we have to pmap() over the three variables.

ggplot() + 
  geom_polygon(data = us_map1, 
               aes(x,y, group = group, fill = Qt), 
               color = "black",
               size = .1) +
  geom_label_repel(data = us_centroids1, 
                   aes(centroid.x, centroid.y, 
                       label = pmap(list(region, Apo, Qt), 
                                    \(x,y,z) bquote(atop(.(x), # first line of lab
                                                         atop(A[po] (km/h) == .(y), # second line
                                                              Q[t] (m/s) == .(z)) # third line
                                                         )
                                                    )
                                    )
                       ),
                   size = 5/14*8,
                   box.padding = 1,
                   parse = T) +
  scale_fill_gradientn(name = expression(Q[t]~(m/s)),
                       breaks = c(0, seq(10,130,20)),
                       labels = c("", seq(10,130,20)),
                       limits = c(0, 130),
                       colors = c("#DCDCDC", "lightblue", "green"),
                       guide = guide_colorbar(barwidth = 0.8, barheight = 18)) +
  theme_void()

Created on 2022-07-31 by the reprex package (v2.0.1)

shs
  • 3,683
  • 1
  • 6
  • 34