我想更新数据帧的一列,使用其原始名称引用它,这可能吗?例如,我说我有表'数据'
a b c
1 2 2
3 2 3
4 1 2
我想将b列的名称更新为'd'。我知道我可以使用
colnames(data)[2] <- 'd'
但是我可以通过专门引用b进行更改,例如
colnames(data)['b'] <- 'd'
因此,如果数据框的列顺序发生更改,则仍会更新正确的列名称。
提前致谢
答案 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"
。正则表达式匹配总是比==
慢,因此对于像这样的简单任务,您可能希望使用简单的==
。