2013-08-22 43 views
7

我在尝试重命名多个data.frame s的列。重命名多个数据框中的列,R

举一个例子,假设我有一个data.frame s dfA,dfBdfC的列表。我写了一个函数changeNames相应地设置名称,然后使用lapply如下:

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

不过,这并不会达到预期效果。看起来我并没有将新名称分配给data.frame,而只是创建新名称。我在这里做错了什么?

预先感谢您!

+0

后行'名称(X)< - '你的功能,加上'回报(X)'或'简单x'。否则,你只是返回'names(x)'。 – Arun

+0

谢谢你的回复阿伦!如果我广告返回(x),我将得到dfA,dfB和dfC的外印,并带有新名称。但是如果我以后查看名称(dfA),名称(dfB)和名称(dfC),它们仍然具有旧的列名称。我的数据框也非常大,所以我不想查看它们。只更改那里的列名称。 – user2706593

+0

'lapply'不会修改输入。这里没有“引用改变”。一切都在副本上完成。你必须重新分配结果。 do:'dfs < - lapply(dfs,ChangeNames)' – Arun

回答

12

这里有两件事情:

  • 1)您应返回从功能所需的值。否则,最后的值将被返回。在你的情况下,这是names(x)。所以,你应该添加最后一行,return(x)或者简单的x。所以,你的函数看起来像:

    ChangeNames <- function(x) { 
        names(x) <- c("A", "B", "C") 
        return(x) 
    } 
    
  • 2)lapply不参照修改您的输入对象。它在一个副本上工作。所以,你必须重新分配结果。或者另一种选择是使用for-loops而不是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映射到没有改变。这些名称已经被引用修改。

+0

使用这个功能来改变列表中包含的多个数据帧的列名是非常有用的。我将这个函数推广到第二个和第三个参数,并将其用作'grep()'的输入来更改我的所有数据框中特定列的名称。 – ano

6

如果数据框不在列表中,而只在全局环境中,则可以使用字符串名称向量来引用它们。

dfs <- c("dfA", "dfB", "dfC") 

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

有可能是为了简化而不必诉诸于创建临时数据集的方式,但我还没有算出来!

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