dplyr'重命名'标准评估功能不按预期工作?

时间:2014-10-28 22:05:54

标签: r dplyr

更新:从这篇文章的下方评论中,现在正如预期的那样工作,没有我在这里提出的问题。

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

我有一个解决方法,如下所示,但我欢迎第二个示例的dplyr解决方案按照我的预期工作,或者解释为什么我不应该期望它按照我希望的方式工作。< / p>

谢谢你, 马特

编辑:我在下面使用rename_添加了一个示例来完成这项工作,但这很复杂。我假设如果哈德利在下面提到的错误得到修复,这将如下所示。但在那之前,我的尴尬方式确实如此,但使用标准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

2 个答案:

答案 0 :(得分:15)

有一些事情让这件事变得痛苦:

  1. c(x = "new")c("x" = "new")相同,而不是相反 c(new = x)

  2. 您可以使用setNames(x, "new")构建所需的矢量, 但...

  3. 我忘了将.dots参数添加到rename_(错误报告位于 https://github.com/hadley/dplyr/issues/708)所以你不能这样做:

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

    相反,您需要使用do.call

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

答案 1 :(得分:2)

在我的Rstudio中,我定义:

x <- 'myname'
dat <- data.frame(yes=1, no=2)

我想将变量名从更改为 myname

它不起作用:

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

但这有效:

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

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