4

When I do:

> quo(DLX6-AS1) 

The output is:

<quosure>
expr: ^DLX6 - AS1
env:  global

Which inserts spaces around the dash.

When I try to convert that to a string, I get either:

quo(DLX6-AS1) %>% quo_name

"DLX6 - AS1"

or

quo(DLX6-AS1) %>% rlang::quo_name

or

quo(`DLX6-AS1`) %>% rlang::quo_name

Error: Can't convert a call to a string

How can I make it possible to use strings with dashes in my function? The function takes in a gene name and looks up that row in a dataframe, but some of the genes are concatenated by a dash:

geneFn <- function(exp.df = seurat.object@data, gene = SOX2) {

    gene <- enquo(gene)

    exp.df <- exp.df[as_name(gene), ] 

}

> geneFn(DLX6-AS1)

Thanks!

This has been asked before here: https://github.com/r-lib/rlang/issues/770 , but it doesn't answer how to actually do this.

Carmen Sandoval
  • 2,266
  • 5
  • 30
  • 46
  • Maybe back-ticks? Like ``rlang::quo(`DLX6-AS1`)``. The `quo_name()` result looks better to me, but I can't test it in your function without a little data reprex. – aosmith Sep 10 '19 at 22:53
  • If you don't want to pass the bare name with backticks around it, another option is to switch to using quoted names instead of bare names. Then you can skip the tidyeval all together and use the gene argument directly for extracting rows: `gene = "SOX2"` then `exp.df[gene, ]` in the function. – aosmith Sep 10 '19 at 23:12
  • Can you share some data so we can test our solutions. The link that I shared to the issue actually tells us some, but I need to test it to be sure. p.s. ```quo(DLX6-AS1) %>% rlang::quo_name()``` this works with no error. – M-- Sep 10 '19 at 23:15
  • can't you just use `gsub` to replace `" - "` with `"-"` – Alex Sep 11 '19 at 05:21

3 Answers3

2

What version of rlang do you have? For me this works:

quo(`DLX6-AS1`) %>% quo_name()
#> [1] "DLX6-AS1"

You do need to use backticks when column names have special characters, otherwise they are interpreted as code.

Note that it is recommended to use either as_name() or as_label() instead of quo_name(), the latter was a misleading misnomer and might be deprecated in the future.

Lionel Henry
  • 6,652
  • 27
  • 33
1

One option would be to stick with bare row names but wrap names that aren't syntactically valid (like names with dashes) in backticks. This could be confusing if someone else is supposed to use this function.

Here's a small, reproducible example:

library(rlang)

dat = data.frame(x1 = letters[1:2],
                 x2 = LETTERS[1:2])
row.names(dat) = c("DLX6-AS1", "other")

geneFn <- function(exp.df = dat, gene = other) {

    gene <- enquo(gene)

    exp.df[as_name(gene), ] 

}

geneFn(gene = other)
#       x1 x2
# other  b  B
geneFn(gene = `DLX6-AS1`)
#          x1 x2
# DLX6-AS1  a  A

If you have many names like this, it may be simpler to pass quoted names instead of bare names. This also simplifies the function a bit since you don't need tidyeval.

geneFn2 <- function(exp.df = dat, gene = "other") {

    exp.df[gene, ] 

}

geneFn2(gene = "other")
#       x1 x2
# other  b  B
geneFn2(gene = "DLX6-AS1")
#          x1 x2
# DLX6-AS1  a  A

Another option is to make syntactically valid names row names. The make.names() function can help with this.

make.names( row.names(dat) )
[1] "DLX6.AS1" "other"  

Then you could assign these new row names to replace the old and go ahead with your original function with the new names.

row.names(dat) = make.names( row.names(dat) )
aosmith
  • 34,856
  • 9
  • 84
  • 118
0

What about:

geneFn <- function(exp.df = seurat.object@data, gene = SOX2) {
    gene <- sub(" - ","-", deparse(enexpr(gene)))
    exp.df <- exp.df[gene, ] 
}
moodymudskipper
  • 46,417
  • 11
  • 121
  • 167