【问题标题】:Rename columns in multiple dataframes, R重命名多个数据框中的列,R
【发布时间】:2013-08-22 09:05:27
【问题描述】:

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

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

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

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

提前谢谢你!

【问题讨论】:

  • 在函数中的names(x) &lt;- 行之后,添加return(x) 或直接添加x。否则,您只会返回 names(x)。
  • 感谢您的回复阿伦!如果我添加 return(x),我将得到一个带有新名称的 dfA、dfB 和 dfC。但是,如果我之后查看名称(dfA)、名称(dfB)和名称(dfC),它们仍然具有旧的列名。我的数据框也很大,所以我没兴趣查看它们。只更改那里的列名。
  • lapply 不会修改输入。这里没有发生“参考更改”。一切都在副本上完成。您必须将结果分配回去。做:dfs &lt;- lapply(dfs, ChangeNames)
  • 好的,dfs 现在是一个包含 dfA、dfB 和 dfC 的大列表,并带有新的列名。我仍然对单独使用 dfA、dfb 和 dfC 感兴趣,并且单独使用它们仍然具有旧的列名?如何将结果分配回各个数据帧?
  • 好吧,你应该把它们分配回去。 dfA &lt;- dfs[[1]]... ?

标签: r dataframe


【解决方案1】:

这里有两件事:

  • 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(.) &lt;- . 可以)。您可以使用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() 的输入,以更改我所有数据框中特定列的名称。
【解决方案2】:

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

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

【讨论】:

    【解决方案3】:

    我遇到了导入公共数据集的问题,并且必须重命名每个数据帧并重命名每个数据帧中的每一列以修剪空格、小写字母并用句点替换内部空格。

    结合以上方法得到了我:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-10-27
      • 2021-03-16
      • 2017-11-06
      • 1970-01-01
      • 1970-01-01
      • 2019-09-05
      • 1970-01-01
      • 2018-12-21
      相关资源
      最近更新 更多