2014-01-08 170 views
37

有人应该已经问过这个问题,但我找不到答案。说我有:按名称重命名多列

x = data.frame(q=1,w=2,e=3, ...and many many columns...) 

什么是最优雅的方式重命名列的任意子集,其位置我并不知道,到一些其它任意名字?

例如假设我想将"q""e"重命名为"A""B",那么执行此操作最优雅的代码是什么?

很显然,我可以做一个循环:

oldnames = c("q","e") 
newnames = c("A","B") 
for(i in 1:2) names(x)[names(x) == oldnames[i]] = newnames[i] 

但我不知道是否有更好的办法?也许使用一些软件包? (plyr::rename等)

回答

61

setnames将在data.frame的工作或data.table小号

library(data.table) 
d <- data.frame(a=1:2,b=2:3,d=4:5) 
setnames(d, old = c('a','d'), new = c('anew','dnew')) 
d 


# anew b dnew 
# 1 1 2 4 
# 2 2 3 5 

请注意,更改是通过引用进行的,因此不需要复制(即使对于data.frames!)

+0

太棒了! upvoted。但我想我应该等一下,看看是否有其他解决方案出现。 – qoheleth

+0

对于迟到的这里 - 也请看下面的[Joel的答案](http://stackoverflow.com/a/36010381/4606130),其中包括检查现有的列,以防您有一个名称更改列表,可能并非所有在场,例如'old = c(“a”,“d”,“e”)' – micstr

4

这将改变这些字母所有出现在所有的名字:从data.table

names(x) <- gsub("q", "A", gsub("e", "B", names(x))) 
+0

我不认为这是特别优雅,一旦你通过几个重命名实例。 – thelatemail

+0

我只是不够好鞭打'gsubfn'的答案。也许G.Grothendieck会过来的。他是正则表达式。 –

3
names(x)[names(x) %in% c("q","e")]<-c("A","B") 
+1

不完全,因为正如我所说的,我不一定知道列的位置,您的解决方案只适用于'oldnames'进行排序,以便'oldnames [i]'出现在'oldnames [j]'之前,学家 – qoheleth

4

大厦@ user3114046的回答是:

x <- data.frame(q=1,w=2,e=3) 
x 
# q w e 
#1 1 2 3 

names(x)[match(oldnames,names(x))] <- newnames 

x 
# A w B 
#1 1 2 3 

这会不会对列在x数据集的特定顺序的依赖。

+0

我已经upvoted你的答案,但我仍然怀疑是否有一个更优雅的方法来做到这一点,特别是通过名称重命名的方法,而不是按位置 – qoheleth

+0

@qoheleth - 它是通过名称更名!这里没有输入是一个位置矢量,因为'match'负责处理这个。你要做的最好的可能是@ mnel的'setnames'回答。 – thelatemail

+0

它仍然是按位置重新命名的,因为正如你所说,即使我不必明确指定位置向量,“匹配”仍然是一个面向位置的命令。本着这种精神,我认为@ user3114046的回答位置也是一样的(甚至认为'%in%'命令关心(或试图)事物)。当然,我认为当我们深入到低级机制时,你可以认为所有的命令都是以位置为导向的......但这不是我的意思...... data.table的答案很好,因为没有多次调用'name'命令。 – qoheleth

24

为dataframes这不是太大的另一个解决方案是(上@thelatemail答案建筑):

x <- data.frame(q=1,w=2,e=3) 

> x 
    q w e 
1 1 2 3 

colnames(x) <- c("A","w","B") 

> x 
    A w B 
1 1 2 3 

或者,你也可以使用:

names(x) <- c("C","w","D") 

> x 
    C w D 
1 1 2 3 

此外,您还可以重命名列名的子集:

names(x)[2:3] <- c("E","F") 

> x 
    C E F 
1 1 2 3 
6

所以我最近碰到了这个,如果你不知道,如果列存在,只是想重新命名那些事:

existing <- match(oldNames,names(x)) 
names(x)[na.omit(existing)] <- newNames[which(!is.na(existing))] 
0

如果一个数据行包含名称要改变所有列,你可以做

names(data) <- data[row,] 

鉴于data是您的数据框,row是包含新值的行号。

然后你就可以删除包含姓名的行与

data <- data[-row,] 
2

你可以得到的名称设置,将其保存为一个列表,然后做字符串批量重命名。一个很好的例子是,当你正在做一个长期的广泛的过渡对数据集:

names(labWide) 
     Lab1 Lab10 Lab11 Lab12 Lab13 Lab14 Lab15 Lab16 
1 35.75366 22.79493 30.32075 34.25637 30.66477 32.04059 24.46663 22.53063 

nameVec <- names(labWide) 
nameVec <- gsub("Lab","LabLat",nameVec) 

names(labWide) <- nameVec 
"LabLat1" "LabLat10" "LabLat11" "LabLat12" "LabLat13" "LabLat14""LabLat15" "LabLat16" " 
+0

这是一个很好的答案,非常一般。 – emilBeBri

16

随着dplyr你会怎么做:

df = data.frame(q = 1, w = 2, e = 3) 

df = df %>% rename(A = q, B = e) 

df 

# A w B 
#1 1 2 3 
0

地块的排序的 - 答案,所以我只是编写该功能,以便复制/粘贴。

rename <- function(x, old_names, new_names) { 
    stopifnot(length(old_names) == length(new_names)) 
    # pull out the names that are actually in x 
    old_nms <- old_names[old_names %in% names(x)] 
    new_nms <- new_names[old_names %in% names(x)] 

    # call out the column names that don't exist 
    not_nms <- setdiff(old_names, old_nms) 
    if(length(not_nms) > 0) { 
     msg <- paste(paste(not_nms, collapse = ", "), 
      "are not columns in the dataframe, so won't be renamed.") 
     warning(msg) 
    } 

    # rename 
    names(x)[names(x) %in% old_nms] <- new_nms 
    x 
} 

x = data.frame(q = 1, w = 2, e = 3) 
rename(x, c("q", "e"), c("Q", "E")) 

    Q w E 
1 1 2 3 
+0

'rename(x,c(“q”,“e”),c(“Q”,“E”))'似乎不再适用于dplyr重命名? – snoram