dplyr中“rename”的替代方法

123
我喜欢plyr的重命名函数rename。我最近开始使用dplyr,想知道是否有一种像plyr的rename函数一样易于使用的dplyr函数来重命名变量?
7个回答

151

dplyr 0.3版本新增了一个名为rename()的函数,它与plyr::rename()一样,但是新旧名称被交换了:

df <- rename(df, new_name = old_name)

7
你能解释一下语法吗?这比命令本身更重要。我正在使用rename(TheDataFrame,OldVarName = NewVarName),但是我收到了Error: Unknown variables: NewVarName.的错误提示,我不明白为什么会出现这种情况。 - s_a
2
@s_a 我已经添加了澄清。审核后应该会显示出来。 - Ryan
4
如果您遇到问题,也许明确指定包名可以帮助解决问题 dplyr::rename(iris, petal_length = Petal.Length) - Boern
3
两个快速观察:以上命令必须分配给数据框才能生效,即iris <- dplyr::rename(iris, petal_length = Petal.Length);并且,rename()函数不能处理带有空格的变量名,例如,dplyr::rename(iris, petal_length = "petal length")会产生一个错误。 - Anthony Simon Mielniczuk
2
如果您要整体替换列名,可以使用setNames()函数:df %>% mutate(foo = 1 +2) %>% setNames(c("blah", "blu", "bar")) - crazybilly
显示剩余2条评论

46

下一个版本的dplyr将支持改进版的select函数,该函数还包括重命名功能:

> mtcars2 <- select( mtcars, disp2 = disp )
> head( mtcars2 )
                  disp2
Mazda RX4         160
Mazda RX4 Wag     160
Datsun 710        108
Hornet 4 Drive    258
Hornet Sportabout 360
Valiant           225
> changes( mtcars, mtcars2 )
Changed variables:
      old         new
disp  0x105500400
disp2             0x105500400

Changed attributes:
      old         new
names 0x106d2cf50 0x106d28a98

2
FYI,“changes”已经被导出(或者应该被导出)。 - hadley
2
很好。唯一的问题是这将意味着用户需要有思想上的转变,因为plyr的重命名函数使用“old”=“new”,而dplyr使用new=old,这样可以与其他dplyr函数保持一致。就我个人而言,我不认为这是一个问题——当它意味着数据处理速度显著提升时,你会很快适应新事物。 - vergilcw
3
这是预期的功能,因此选择使用动词“select”。不确定我们是否有一项功能可以选择所有变量,并且重命名该列。 - Romain Francois
1
也许为了避免混淆,您可以编辑您的帖子,以便代码反映出select实际的行为方式?我会投票支持一种简单的dplyr方法来保留所有变量并只重命名一个或两个变量。:) 目前我会继续加载plyr并使用rename - vergilcw
2
@RomainFrancois @aaronwolen 你可以使用 mtcars %>% select(matches(".*"),disp2=disp) 来实现OP想要的功能。我希望有一个更简洁的解决方案,但这个方法可以工作并保留所有列(尽管不保留它们的顺序)。disp不会被重复。 - farnsy
显示剩余5条评论

27

实际上,您可以将plyrrename函数作为dplyr链的一部分使用。我认为每个函数都符合以下两个条件:a)以data.frame作为第一个参数,b)返回data.frame,因此都适用于链接。以下是一个示例:

library('plyr')
library('dplyr')

DF = data.frame(var=1:5)

DF %>%
    # `rename` from `plyr`
    rename(c('var'='x')) %>%
    # `mutate` from `dplyr` (note order in which libraries are loaded)
    mutate(x.sq=x^2)

#   x x.sq
# 1 1    1
# 2 2    4
# 3 3    9
# 4 4   16
# 5 5   25
更新:当前版本的dplyr支持直接在select函数中进行重命名(请参见上面Romain Francois的帖子)。然而,有关将非dplyr函数用作dplyr链的一般性说明仍然有效,而rename是一个有趣的例子。

5
在这种情况下最好先加载plyr再加载dplyr。这样,当可用时会使用更快的dplyr函数,您可以使用mutate而不是dplyr :: mutate。 - Vincent
看起来你是对的,可以在链式操作中使用非dplyr函数。mtcars %.% rename(c("mpg","cyl"), c("mympg","mycyl")) 这个例子是有效的,其中rename是我回答中定义的函数。 - Vincent
我改变了dplyr和plyr的加载顺序,谢谢。 - user2503795
这是一个不错的解决方法,但它引发了一场有趣的讨论,即关于在处理大数据时的性能问题,这也是 dplyr 的主要优势之一。感谢您的建议! - vergilcw
重命名函数(如 data.table 包中的 setnames)是否像引用一样使用 rename 函数? - MySchizoBuddy

9

这个函数在dplyr中没有列为功能(尚未):http://cran.rstudio.org/web/packages/dplyr/dplyr.pdf

如果你不想加载plyr和dplyr,下面的函数几乎相同

rename <- function(dat, oldnames, newnames) {
  datnames <- colnames(dat)
  datnames[which(datnames %in% oldnames)] <- newnames
  colnames(dat) <- datnames
  dat
}

dat <- rename(mtcars,c("mpg","cyl"), c("mympg","mycyl"))
head(dat)

                  mympg mycyl disp  hp drat    wt  qsec vs am gear carb
Mazda RX4          21.0     6  160 110 3.90 2.620 16.46  0  1    4    4
Mazda RX4 Wag      21.0     6  160 110 3.90 2.875 17.02  0  1    4    4
Datsun 710         22.8     4  108  93 3.85 2.320 18.61  1  1    4    1
Hornet 4 Drive     21.4     6  258 110 3.08 3.215 19.44  1  0    3    1
Hornet Sportabout  18.7     8  360 175 3.15 3.440 17.02  0  0    3    2
Valiant            18.1     6  225 105 2.76 3.460 20.22  1  0    3    1

编辑:Romain的评论产生了以下结果(请注意,更改函数需要dplyr .1.1)

> dplyr:::changes(mtcars, dat)
Changed variables:
          old         new        
disp      0x108b4b0e0 0x108b4e370
hp        0x108b4b210 0x108b4e4a0
drat      0x108b4b340 0x108b4e5d0
wt        0x108b4b470 0x108b4e700
qsec      0x108b4b5a0 0x108b4e830
vs        0x108b4b6d0 0x108b4e960
am        0x108b4b800 0x108b4ea90
gear      0x108b4b930 0x108b4ebc0
carb      0x108b4ba60 0x108b4ecf0
mpg       0x1033ee7c0            
cyl       0x10331d3d0            
mympg                 0x108b4e110
mycyl                 0x108b4e240

Changed attributes:
          old         new        
names     0x10c100558 0x10c2ea3f0
row.names 0x108b4bb90 0x108b4ee20
class     0x103bd8988 0x103bd8f58

3
唯一的问题在于数据被复制了。如果只是用于玩耍,例如 mtcars 等等,那倒也无所谓,但是如果你处理的是大量数据,这就相当重要了。请查看 dplyr:::changes(mtcars, dat) - Romain Francois
1
谢谢你的评论,Romain。为什么dplyr没有导出changes呢?它似乎是一个非常有用的函数。 - Vincent
1
我猜Hadley主要把它视为我们的开发工具。 - Romain Francois
1
它肯定应该被导出。我可能只是忘记了。 - hadley

2

虽然并不是重命名,但是dplyr::select_all()可以用来重新格式化列名。以下示例将空格和句号替换为下划线,并将所有内容转换为小写:

iris %>%  
  select_all(~gsub("\\s+|\\.", "_", .)) %>% 
  select_all(tolower) %>% 
  head(2)
  sepal_length sepal_width petal_length petal_width species
1          5.1         3.5          1.4         0.2  setosa
2          4.9         3.0          1.4         0.2  setosa

1

我尝试使用dplyr::rename,但是出现了错误:

occ_5d <- dplyr::rename(occ_5d, rowname='code_5d')
Error: Unknown column `code_5d` 
Call `rlang::last_error()` to see a backtrace

我使用了基本的 R 函数,它非常简单而有效:
names(occ_5d)[1] = "code_5d"

0

dplyr >= 1.0.0

除了较新版本的dplyr::rename之外,还有rename_with()

使用函数重命名列。

您可以使用.cols参数在tidy-select一组列上应用函数:

iris %>% 
  dplyr::rename_with(.fn = ~ gsub("^S", "s", .), .cols = where(is.numeric))

    sepal.Length sepal.Width Petal.Length Petal.Width    Species
1            5.1         3.5          1.4         0.2     setosa
2            4.9         3.0          1.4         0.2     setosa
3            4.7         3.2          1.3         0.2     setosa
4            4.6         3.1          1.5         0.2     setosa
5            5.0         3.6          1.4         0.2     setosa

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