重命名 R 中的一个命名列

Posted

技术标签:

【中文标题】重命名 R 中的一个命名列【英文标题】:Rename one named column in R 【发布时间】:2012-05-18 15:25:52 【问题描述】:

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

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

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

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

但我可以通过专门引用 b 来进行更改,即类似

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

这样,如果数据框的列顺序发生变化,正确的列名仍会更新。

提前致谢

【问题讨论】:

好问题!正在尝试这个:colnames(data['b']) &lt;- 'd',也不好!正如蔡斯指出的那样,这就是方式:colnames(data)[colnames(data) == "b"] &lt;- "d" 【参考方案1】:

有一个函数 setnames 内置在包 data.table 中。

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

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

DT 必须输入 data.table 才能使 setnames 工作。所以你需要切换到data.table 或使用as.data.table 转换,才能使用它。

这是来自?setnames 的摘录。目的是您在提示符下运行 example(setnames),然后 cmets 与您看到的 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.

【讨论】:

但是为了简单的列重命名而加载新包值得所有的喧嚣吗? =) 绝对。它可以在out of memory 之间产生差异,或者不是。而且它更短、更容易,而且出现错误的机会也更少。 @Tyler 在 r-devel 上有两个(相当长的)线程:speeding up perception 和(可能是最相关的)confused about NAMED 和可能其他。 @Tyler 现在在这些显示 data.table 速度较慢的基准上,你能指点我一个吗? @MatthewDowle -- 刚刚在您的示例中添加了一个 tracemem 测试,只是 b/c 变量 R 的行为有点搞笑,而且 b/c 我有点喜欢倒计时4, 3, 2, 1, ... data.table .【参考方案2】:

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

rename(data, d = b)

【讨论】:

【参考方案3】:

这似乎是一个 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

【讨论】:

或者你可以简单地使用colnames(dat) == 'b'索引列名,但不管你做什么,它都会是循环的。 不要将正则表达式用于这样的简单内容。我宁愿坚持使用简单的== 关系运算符。 乍一看,我认为 Chase 使用了agrep,这可能有一些优势。 @aL3xa,如果您有许多相似的列前缀/后缀要重命名,gsub 非常宝贵。但是,一个孤立的案例通常是矫枉过正的。【参考方案4】:

是的,但它比数字索引更难(据我所知)。我将提供一个脏函数来执行此操作,如果您想了解如何执行此操作,只需逐行撕开该函数:

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')

【讨论】:

【参考方案5】:

我不同意@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"。正则表达式匹配总是==慢,所以对于像这样的简单任务,您可能需要使用简单的==

【讨论】:

我想我在回答中指出我确信有更好的答案,特别是 I'm sure there are better options 部分。正如 Joran 在 cmets 中指出的那样,直接使用 == 更好,我现在也认识到并在我的答案中展示了一个示例:) 为了后代,我将保留上半部分。 这个答案与我的基本相同,因为我使用colnames(d) %in% "b"。在这种情况下,他们正在做同样的事情,尽管我认为== 会更快。

以上是关于重命名 R 中的一个命名列的主要内容,如果未能解决你的问题,请参考以下文章

重命名 Pyspark Dataframe 中的未命名列

熊猫按位置重命名列? [复制]

重命名 mysql 表中的列,而不必重复其类型定义

重命名mysql表中的列而不必重复其类型定义

熊猫重命名列

如何使用 Visual Studio 数据库项目重命名列?