在多个数据框中重命名列,R

14

我正在尝试重命名多个data.frame的列。

举例来说,假设我有一个data.frame列表包含dfAdfBdfC。我编写了一个changeNames函数来设置名称,并按照以下方式使用lapply

dfs <- list(dfA, dfB, dfC)
ChangeNames <- function(x) {
    names(x) <- c("A", "B", "C" )  
}
lapply(dfs, ChangeNames)

然而,这并没有按照预期工作。似乎我没有将新名称分配给 data.frame,而只是创建了新名称。在这里我做错了什么?

提前感谢!


在你的函数中,在names(x) <-这一行后面添加return(x)或者简单地写成x。否则,你只会返回names(x) - Arun
谢谢您的回复,Arun!如果我添加return(x),我将得到dfA、dfB和dfC的输出,并带有新名称。但是,如果之后查看names(dfA)、names(dfB)和names(dfC),它们仍然具有旧的列名称。我的数据框也非常大,所以我不想查看它们,只想更改它们的列名称。 - user2706593
lapply 不会修改输入。这里没有发生“引用更改”。所有操作都在副本上完成。您必须将结果重新赋值。执行:dfs <- lapply(dfs, ChangeNames) - Arun
好的,现在dfs是一个包含dfA、dfB和dfC的大列表,具有新的列名。我仍然希望单独处理dfA、dfB和dfC,并且它们仍然具有旧的列名?我该如何将结果分配回各个数据框? - user2706593
好的,你应该将它们重新分配。dfA <- dfs[[1]]...? - Arun
3个回答

16

这里有两件事:

  • 1) 你应该从你的函数中返回你想要的值。否则,将返回最后一个值。在你的情况下,那是names(x)。所以,你应该添加最后一行return(x)或者简单地写成x。所以,你的函数应该像这样:

    ChangeNames <- function(x) {
        names(x) <- c("A", "B", "C" )
        return(x)
    }
    
  • 2) lapply不会通过引用修改您的输入对象。它在副本上工作。因此,您将不得不将结果分配回去。或者另一种选择是使用for循环而不是lapply

  • # option 1
    dfs <- lapply(dfs, ChangeNames)
    
    # option 2
    for (i in seq_along(dfs)) {
        names(dfs[[i]]) <- c("A", "B", "C")
    }
    

即使使用for-loop,您仍然会制作副本(因为 names(.) <- . 会这样做)。 您可以使用tracemem进行验证。

df <- data.frame(x=1:5, y=6:10, z=11:15)
tracemem(df)
# [1] "<0x7f98ec24a480>"
names(df) <- c("A", "B", "C")
tracemem(df)
# [1] "<0x7f98e7f9e318>"

如果您想通过引用进行修改,可以使用 data.table 包的 setnames 函数:

df <- data.frame(x=1:5, y=6:10, z=11:15)
require(data.table)
tracemem(df)
# [1] "<0x7f98ec76d7b0>"
setnames(df, c("A", "B", "C"))
tracemem(df)
# [1] "<0x7f98ec76d7b0>"

你会发现内存位置df映射到的内容没有改变。名称通过引用进行了修改。


使用此函数来更改包含在列表中的多个数据框中的列名非常有帮助。我将函数泛化,以接受第二个和第三个参数,并将其用作 grep() 的输入,以更改所有数据框中特定列的名称。 - ano

13
如果数据框不是在列表中而只是在全局环境中,您可以使用字符串名称的向量来引用它们。
dfs <- c("dfA", "dfB", "dfC")

for(df in dfs) {
  df.tmp <- get(df)
  names(df.tmp) <- c("A", "B", "C" ) 
  assign(df, df.tmp)
}

编辑

为了简化上述代码,你可以使用:

for(df in dfs)
  assign(df, setNames(get(df),  c("A", "B", "C")))

或者使用不需要重新赋值的data.table

for(df in c("dfA", "dfB"))
  data.table::setnames(get(df),  c("G", "H"))

-1

我曾经遇到一个问题,需要导入公共数据集并且需要重命名每个数据框架以及在每个数据框架中重命名每个列以修剪空格、变成小写并将内部空格替换为句号。

结合以上方法,我得到了以下结果:

for (eachdf in dfs)
  df.tmp <- get(eachdf) 
    for (eachcol in 1:length(df.tmp))
      colnames(df.tmp)[eachcol] <-
      str_trim(str_to_lower(str_replace_all(colnames(df.tmp)[eachcol], " ", ".")))
      }
  assign(eachdf, df.tmp) 
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接