17

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

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

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

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

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

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

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

提前致谢

4

5 回答 5

30

setnames包中内置了一个功能data.table

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.
于 2012-05-18T16:02:52.817 回答
14

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

rename(data, d = b)
于 2015-01-19T14:20:25.937 回答
13

这似乎是一种 hack,但首先想到的是使用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

正如 Joran 在下面指出的那样,我把事情复杂化了……根本不需要正则表达式。这也节省了打字时的几个字符。

colnames(dat)[colnames(dat) == "foo"] <- "bar"
#------
  a bar c
1 1   1 1
2 2   2 2
3 3   3 3
于 2012-05-18T15:36:02.433 回答
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')
于 2012-05-18T15:34:28.893 回答
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)). 要么 pass fixed = TRUE,要么更好地colnames(d) == "b"像@joran 建议的那样做简单的事情。正则表达式匹配总是比它慢==,所以对于像这样的简单任务,您可能需要使用 simple ==

于 2012-05-18T15:59:43.477 回答