Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
556 views
in Technique[技术] by (71.8m points)

r - dplyr 'rename' standard evaluation function not working as expected?

UPDATE: From comment below on this post, this is now working as expected, without the issues I laid out here.

Below is a toy example of using rename_ from dplyr. I was expecting to be able to change the column name back to it's original name using the second example below, but I'm guessing that function argument evaluation rules are somehow preventing it from working the way I think. There is an easy workaround using the original plyr package rename function (as well as using the base package names function), but I have a feeling I'm missing a dplyr solution to this.

I have a workaround as shown below, but I'd welcome both a dplyr solution to the second example working as I expect, or an explanation of why I shouldn't expect it to work the way I want it to.

Thank you, Matt

EDIT: I added an example below using rename_ to make this work, but is complicated. I assume if the bug that Hadley refers to below gets fixed, this will work as he shows below. But until then, my awkward way does, but it is probably better to use the standard plyr method. Also added base R technique at end for example completeness.

library(plyr)
library(dplyr)

# dataframe to operate on
dat <- data_frame(a=1, b=1)

# identifier with string of column name in dat
x <- "a"


# Renaming using standard evaluation this way works
dat %>%
    rename_("new" = x)
# Source: local data frame [1 x 2]
# 
#   new b
# 1   1 1


# But changing it back does not
# I expect "a" to be the name, not the identifier x
dat %>%
    rename_("new" = x) %>%
    rename_(x = "new")
# Source: local data frame [1 x 2]
# 
#   x b
# 1 1 1


# This works, but seems really awkward...
dat %>%
    rename_("newname" = x) %>%
    do(do.call(rename_, setNames(list(., "newname"), c(".data", x))))

# Source: local data frame [1 x 2]
# 
#   a b
# 1 1 1


# This works fine
dat %>%
    rename_("new" = x) %>%
    plyr::rename(c("new" = x))
# Source: local data frame [1 x 2]
# 
#   a b
# 1 1 1


# Base R way
datrn <- dat %>%
    rename_("newname" = x)
names(datrn)[names(datrn) == "newname"] = x
datrn
# Source: local data frame [1 x 2]
# 
#   a b
# 1 1 1
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

There are a few thing that make this painful:

  1. c(x = "new") is the same as c("x" = "new"), and not the opposite of c(new = x).

  2. You can construct the vector you want with setNames(x, "new"), but...

  3. I forgot to add the .dots argument to rename_ (bug report at https://github.com/hadley/dplyr/issues/708) so you can't do:

    rename_(dat, .dots = setNames(x, "new"))
    

    Instead you need to use do.call:

    do.call(rename_, c(list(quote(dat)), list(setNames(x, "new"))))
    

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...