dplyr rename_ produces an error when renaming columns with spaces

6.7k Views Asked by At

rename_ works as expected for non-pathological column names

%>% rename_(foo = 'testcol')

But what if I'd like to rename a column which has a space?

%>% rename_(foo = 'test col')

I get an error that says:

Error in parse(text = x) (from #12) : <text>:1:6: unexpected symbol

I could use make.names but is there no way to rename a column without that extra step?

2

There are 2 best solutions below

3
On BEST ANSWER

You can try with backquotes

%>% rename(foo = `test col`)

Using a reproducible example

library(dplyr)
df %>% 
    rename(foo = `test col`) %>%
    head(3)
#        Col1 foo
#1 -0.5458808   C
#2  0.5365853   N
#3  0.4196231   R

Or using rename_ (though I am not sure if this is correct syntax as usually .dots are needed.) Using similar syntax from OP's post

df %>%
      rename_(foo = quote(`test col`)) %>%
       head(3)
#        Col1 foo
#1 -0.5458808   C
#2  0.5365853   N
#3  0.4196231   R

data

 set.seed(24)
 df <- data.frame(Col1= rnorm(10), 'test col' = sample(LETTERS, 10),
        check.names=FALSE)
0
On

Here is the underlying reason for this behavior. To fix the problem, @akrun's answer is probably more suitable.

Most dplyr functions use lazyeval internally. And the character method for lazyeval::as.lazy cannot handle spaces. A possible fix would be to add the around character strings with spaces insideas.lazy.character`.

require(lazyeval)
as.lazy.character <- function (x, env = baseenv()){
  if (grepl(pattern = "[:space:]", x) & !grepl(pattern = "`", x))
    x <- paste0("`", x, "`")
  lazy_(parse(text = x)[[1]], env)
}

Or better yet (from @hadley's suggestion)

as.lazy.character <- function (x, env = baseenv()){
  if (grepl(pattern = "[:space:]", x) & !grepl(pattern = "`", x))
    return(as.lazy(as.name(x), env))
  lazy_(parse(text = x)[[1]], env)
}

That fixes the rename_, as well as any other functions using as.lazy internally:

dplyr::select_vars_(names(df), "test col")
dplyr::rename_(df, foo="test col")
dplyr::mutate_(df, "foo" = "test col" )