Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

dplyr rename_ produces an error when renaming columns with spaces

Tags:

r

dplyr

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?

like image 692
daj Avatar asked Jun 12 '15 04:06

daj


People also ask

How do I rename a column in R using dplyr?

rename() function from dplyr takes a syntax rename(new_column_name = old_column_name) to change the column from old to a new name. The following example renames the column from id to c1 . The operator – %>% is used to load the renamed column names to the data frame.

How do I change a column name in R rename?

To rename a column in R, you can use the rename() function from dplyr. For example, if you want to rename the column “A” to “B” again, you can run the following code: rename(dataframe, B = A) .

How do I rename multiple columns in R?

To change multiple column names by name and by index use rename() function of the dplyr package and to rename by just name use setnames() from data. table . From R base functionality, we have colnames() and names() functions that can be used to rename a data frame column by a single index or name.

What does rename function do in R?

rename() function in R Language is used to rename the column names of a data frame, based on the older names.


2 Answers

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)
like image 142
akrun Avatar answered Sep 30 '22 11:09

akrun


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" )
like image 39
shadow Avatar answered Sep 30 '22 12:09

shadow