dplyr的'rename'标准评估函数不能按预期工作?

15

更新:来自本帖下方评论的信息,现在已经按照预期工作,没有我在此处提出的问题。

以下是使用dplyr中的rename_的玩具示例。我希望能够通过下面的第二个示例更改列名回到原始名称,但我猜想函数参数评估规则以某种方式阻止了它按照我的想法工作。使用原始的plyr包rename函数(以及使用基本包names函数)有一个简单的解决方法,但我觉得我错过了dplyr的解决方案。

我已经展示了一个解决方法,但我欢迎解决第二个示例按照我的期望工作的方法,或者解释为什么我不应该期望它按照我想要的方式工作。

谢谢, Matt

编辑:我添加了下面的一个示例,使用rename_使其工作,但很复杂。我假设如果Hadley所提到的错误得到修复,这将按照他所展示的方式工作。但在那之前,我尴尬的方法确实可以用,但使用标准的plyr方法可能更好。还添加了基于R的技术以实现完整性。

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

8
如果有人想知道,rename_(dat, .dots = setNames(x, "new"))现在按预期工作。 - cboettig
更多关于这类问题的信息可以在dplyr的非标准评估vignette中获得:https://cran.r-project.org/web/packages/dplyr/vignettes/nse.html - RobinL
2个回答

16

有几件事情使得这很痛苦:

  1. c(x = "new")c("x" = "new") 是一样的,而不是与 c(new = x) 相反。

  2. 你可以使用 setNames(x, "new") 来构建你想要的向量,但是...

  3. 我忘记在 rename_ 中添加 .dots 参数(在https://github.com/hadley/dplyr/issues/708上报告了 bug),所以你不能这样做:

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

    相反,您需要使用do.call

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

所以,我正在尝试让do.call的例子起作用,但是我没有成功。不确定如何将dat对象合并到该调用中,因为它在调用本身中没有被引用。 - mpettis
在尝试各种方式使用 setNames 时,我遇到了以下类型的错误:All arguments to rename must be named.FALSE - mpettis
@mpettis 那个 do.call 调用应该会更好一些。 - hadley
我尝试了这个变化并得到了以下错误信息:> do.call(rename_, list(dat, setNames(x, "new"))) Error in rename_vars_(names(.data), dots) : All arguments to rename must be named.FALSE - mpettis
这是我能够使其工作的 do.call 结构:do.call(rename_, setNames(list(datrn, "new"), c(".data", x))) - mpettis

2
在我的Rstudio中,我定义了:
x <- 'myname'
dat <- data.frame(yes=1, no=2)

我想把变量名从yes改成myname

但是它不起作用:

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

但这个可以运行:
rename_(dat, .dots = setNames("yes", x))

rename_(dat, .dots = setNames("yes", paste(x) ))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接