重命名R中的一个命名列

时间:2012-05-18 15:25:53

标签: r dataframe

我想更新数据帧的一列,使用其原始名称引用它,这可能吗?例如,我说我有表'数据'

a b c  
1 2 2  
3 2 3  
4 1 2

我想将b列的名称更新为'd'。我知道我可以使用

colnames(data)[2] <- 'd'  

但是我可以通过专门引用b进行更改,例如

colnames(data)['b'] <- 'd'  

因此,如果数据框的列顺序发生更改,则仍会更新正确的列名称。

提前致谢

5 个答案:

答案 0 :(得分:25)

data.table包中内置了一个函数setnames

setnames(DT, "b", "d")

它通过引用更改名称,完全没有副本。使用names(data)<-names(data)[i]<-或类似方法的任何其他方法都会复制整个对象,通常会复制几次。即使您正在做的只是更改列名。

DT必须为data.table setnames才能正常工作。因此,您需要切换到data.table或使用as.data.table进行转换,才能使用它。

以下是?setnames的摘录。目的是在提示符处运行example(setnames),然后注释与tracemem报告的副本相关。

DF = data.frame(a=1:2,b=3:4)       # base data.frame to demo copies
tracemem(DF)
colnames(DF)[1] <- "A"             # 4 copies of entire object
names(DF)[1] <- "A"                # 3 copies of entire object
names(DF) <- c("A", "b")           # 2 copies of entire object
`names<-`(DF,c("A","b"))           # 1 copy of entire object
x=`names<-`(DF,c("A","b"))         # still 1 copy (so not print method)

# What if DF is large, say 10GB in RAM. Copy 10GB just to change a column name?

DT = data.table(a=1:2,b=3:4,c=5:6)
tracemem(DT)
setnames(DT,"b","B")               # by name; no match() needed. No copy.
setnames(DT,3,"C")                 # by position. No copy.
setnames(DT,2:3,c("D","E"))        # multiple. No copy.
setnames(DT,c("a","E"),c("A","F")) # multiple by name. No copy.
setnames(DT,c("X","Y","Z"))        # replace all. No copy.

答案 1 :(得分:11)

这看起来像是一个黑客,但首先想到的是使用grepl()一个足够详细的搜索字符串来获取你想要的列。我相信有更好的选择:

dat <- data.frame(a = 1:3, b = 1:3, c = 1:3)
colnames(dat)[grepl("b", colnames(dat))] <- "foo"
dat
#------
  a foo c
1 1   1 1
2 2   2 2
3 3   3 3

正如乔兰在下面指出的那样,我过于复杂化......根本不需要正则表达式。这样就可以节省一些字符。

colnames(dat)[colnames(dat) == "foo"] <- "bar"
#------
  a bar c
1 1   1 1
2 2   2 2
3 3   3 3

答案 2 :(得分:6)

截至2014年10月,现在可以在dplyr包中轻松完成:

rename(data, d = b)

答案 3 :(得分:3)

是的但是(据我所知)比数字索引更困难。我将提供一个可以执行此操作的脏功能,如果您想要查看如何执行此功能,请将功能逐行拆开:

rename <- function(df, column, new){
    x <- names(df)                               #Did this to avoid typing twice
    if (is.numeric(column)) column <- x[column]  #Take numeric input by indexing
    names(df)[x %in% column] <- new              #What you're interested in
    return(df)
}

#try it out
rename(mtcars, 'mpg', 'NEW')
rename(mtcars, 1, 'NEW')

答案 4 :(得分:1)

我不同意@Chase - grepl解决方案不是最幸运的解决方案。我会说:选择简单的==。原因如下:

d <- data.frame(matrix(rnorm(100), 10))
colnames(d) <- replicate(10, paste(sample(letters[1:5], size = 5, replace=TRUE, prob=c(.1, .6, .1, .1, .1)), collapse = ""))

现在尝试grepl("b", colnames(d))。要么通过fixed = TRUE,要么更好地做@ joran建议的简单colnames(d) == "b"。正则表达式匹配总是==慢,因此对于像这样的简单任务,您可能希望使用简单的==