Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

extracting column attribute inside a function

Say I have the following tibble:

df1 <- structure(list(var1 = structure(c("Didn't do a thing", "Almost did a thing", 
"Once did a thing", "Have never done a thing", "Always do a thing"
), description = "This is the question i asked respondents (and the title of the plot)"), 
    wtd_pct = c(4L, 15L, 62L, 11L, 8L)), row.names = c(NA, -5L
), class = c("tbl_df", "tbl", "data.frame"))

I want to make a plot function that takes as inputs the name of the tibble (df1) and the name of a column inside it (in this case, there is only var1, but in my actual tibble I have many more columns).

Inside the plot function I want to pull out the attribute connected to var1 and make that the plot title. For example, outside a function this looks like this:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

df1 %>% 
  ggplot(aes(y = var1, x = wtd_pct)) +
  geom_col(aes(fill = var1)) +
  geom_text(aes(label = paste0(round(wtd_pct, 0), "%")), size = 3.5, vjust = -.5, hjust = -.3, color = 'black') +
  theme_minimal() + theme(legend.position = "none") +
  labs(y = "", 
       x = "Weighted percent", 
       title = paste0("\"", str_wrap(attr(df1$var1, "description"), 100), "\""))

Note the title line above. However, when I put this inside a function and attempt to call it I get all sorts of errors. E.g.

plot_function <- function(.x, .y){
.x %>% 
  ggplot(aes(y = {{.y}}, x = wtd_pct)) +
  geom_col(aes(fill = {{.y}})) +
  geom_text(aes(label = paste0(round(wtd_pct, 0), "%")), size = 3.5, vjust = -.5, hjust = -.3, color = 'black') +
  theme_minimal() + theme(legend.position = "none") +
  labs(y = "", 
       x = "Weighted percent", 
       title = paste0("\"", str_wrap(attr({{.x$.y}}, "description"), 100), "\""))
}

plot_function(df1, var1)

This returns the plot but with no title + the error Warning message: Unknown or uninitialised column: .y.. I’ve tried various other things (wrapping in !!ensym(), .data[[]], extracting the attribute first into a separate string, etc., but I never get what I want.

It seems the crux of the issue is that you can’t pipe df into attr(), but it also doesn’t like the .x$.y syntax. Can anyone here point me in the right direction?

>Solution :

The $ operator uses non-standard evaluation without substituting, so .x$.y will be interpreted as "the column called .y inside df1", which of course does not exist.

The usual way round this is to use [[ instead of $, but this is a little trickier here because you want to pass an unquoted column name.

One option is to use .x[[deparse(substitute(.y))]] (without the curly-curly operators)

plot_function <- function(.x, .y){
  .x %>% 
    ggplot(aes(y = {{.y}}, x = wtd_pct)) +
    geom_col(aes(fill = {{.y}})) +
    geom_text(aes(label = paste0(round(wtd_pct, 0), "%")), 
              size = 3.5, vjust = -.5, hjust = -.3, color = 'black') +
    theme_minimal() + theme(legend.position = "none") +
    labs(y = "", 
         x = "Weighted percent", 
         title = paste0("\"", str_wrap(attr(.x[[deparse(substitute(.y))]],
                                            "description"), 100), "\""))
}

plot_function(df1, var1)

enter image description here

A pure tidyverse equivalent might be to use something like

rlang::eval_tidy(enquo(.y), data = .x)

in place of .x[[deparse(substitute(.y))]]

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading