在R中更改数据框列表中的列名

33

目标:更改全局环境中以下列表中所有数据框的列名。

全局环境中的列名

所以,

0) 列名为:

 colnames = c("USAF","WBAN","YR--MODAHRMN") 

1) 我有以下数据框:df1,df2。

2) 我将它们放入列表中:

  dfList <- list(df1,df2)

3) 遍历列表:

 for (df in dfList){
   colnames(df)=colnames
 }

但是这会创建一个新的数据框,并列出我需要的列名,它不会改变 df1、df2 中原始的列名。为什么?可能使用 lapply 是一个解决方法吗?谢谢。

以下内容是否可行:

 lapply(dfList, function(x) {colnames(dfList)=colnames})

工作?

6个回答

52
可以按照以下方式完成。

创建示例数据:

df1 <- data.frame(A = 1, B = 2, C = 3)
df2 <- data.frame(X = 1, Y = 2, Z = 3)
dfList <- list(df1,df2)
colnames <- c("USAF","WBAN","YR--MODAHRMN") 

然后使用setNames在列表上执行lapply,并将新列名向量作为第二个参数提供给setNames:

lapply(dfList, setNames, colnames)
#[[1]]
#  USAF WBAN YR--MODAHRMN
#1    1    2            3
#
#[[2]]
#  USAF WBAN YR--MODAHRMN
#1    1    2            3

编辑

如果你想将这些数据框重新分配到全局环境中,你可以修改代码如下:

dfList <- list(df1 = df1, df2 = df2)
list2env(lapply(dfList, setNames, colnames), .GlobalEnv)

@Oniropolo,请查看我的编辑。这将更改您在全局环境中的原始数据框。 - talat
这对于我来说超出了我的R知识水平,但我正在阅读关于环境的内容。我能问你为什么1)你不创建一个新的环境而是创建一个列表?2)那么假设你需要进行一些数据清洗,比如strptime(df1$YR--MODAHRMN,format ='%Y%m%d%H%M')。是否有可能创建一个环境,然后修改这个新环境中的所有元素?非常抱歉我知识的匮乏! - Oniropolo
1
@Oniropolo,你的问题是基于有一个数据框列表,你想要更改名称 - 这就是为什么我使用了列表结构.. 通常,如果你有许多某种相关的数据框,最好将它们保存在一个列表中(即不将它们分配回全局环境)。一般来说,我几乎从不创建额外的环境,但这取决于个人编程偏好,我想。 - talat
非常感谢!在您的回答之前,我不知道什么是环境! - Oniropolo

13

只需将您的for循环更改为类似于以下的索引for循环:

Data

df1 <- data.frame(a=runif(5), b=runif(5), c=runif(5))
df2 <- data.frame(a=runif(5), b=runif(5), c=runif(5))

dflist <- list(df1,df2)

colnames = c("USAF","WBAN","YR--MODAHRMN") 

解决方案

for (i in seq_along(dflist)){
  colnames(dflist[[i]]) <- colnames
}

输出

> dflist
[[1]]
       USAF      WBAN YR--MODAHRMN
1 0.8794153 0.7025747    0.2136040
2 0.8805788 0.8253530    0.5467952
3 0.1719539 0.5303908    0.5965716
4 0.9682567 0.5137464    0.4038919
5 0.3172674 0.1403439    0.1539121

[[2]]
        USAF       WBAN YR--MODAHRMN
1 0.20558383 0.62651334    0.4365940
2 0.43330717 0.85807280    0.2509677
3 0.32614750 0.70782919    0.6319263
4 0.02957656 0.46523151    0.2087086
5 0.58757198 0.09633181    0.6941896

当使用 for (df in dfList) 时,实际上每次都会创建一个新的 DataFrame,并将列名更改为该数据框的名称,从而不会影响原始列表 (dfList)。


为什么执行 colnames(df2) 后返回原始值 [1] "a" "b" "c"? - Oniropolo
那么问题是如何更改原始的df2?重要的列是原始的df1、df2;列表只是在一个循环中同时更改两者的一种方式。 - Oniropolo
我在上面提供了一个解决方案:df2 <- dflist[[2]] - LyzandeR
1
哦,最简单的代码行。为什么我没想到呢。谢谢! - Oniropolo
@Oniropolo,请编辑你的问题的第一行,以反映你想要更改全局环境中的列名,而不是列表中的data.frames的列名。 - StrikeR
显示剩余2条评论

1
一个使用 rename_withtidyverse 解决方案:
library(dplyr)
library(purrr)

map(dflist, ~ rename_with(., ~ colnames))

或者,如果只是针对一列:

map(dflist, ~ rename(., new_col = old_col))

这也适用于 lapply

lapply(dflist, rename_with, ~ colnames)
lapply(dflist, rename, new_col = old_col)

1
如果您想让 for 循环正常工作,不应将整个数据框作为参数传递。
for (df in 1:length(dfList))
  colnames(dfList[[df]]) <- colnames

我真的不明白... 举个例子,就拿第一个人给出的例子来说,使用你的代码,我仍然得到的是 colnames(df2) ...[1] "X" "Y" "Z"。 - Oniropolo
在你谈到的那个答案中,df2是一个data.frame,与dfList没有任何关系,而dfList是df1和df2的组合。因此,在dfList内部存在的df2中更改了名称。查看colnames(dfList$df2)以获取更改后的列名。 - StrikeR

0
dfList <- lapply(dfList, `names<-`, colnames)

虽然这段代码片段可能解决了问题,但包括解释真的有助于提高您的帖子质量。请记住,您正在为未来的读者回答问题,而这些人可能不知道您的代码建议原因。 - Gerhard
也许...这仍然比被接受的解决方案要好 :) - Dan Lewer

0
创建示例数据:
df1 <- data.frame(A = 1, B = 2, C = 3)
df2 <- data.frame(X = 1, Y = 2, Z = 3)
dfList <- list(df1,df2)
name <- c("USAF","WBAN","YR--MODAHRMN")

接下来创建一个函数来设置列名:

res=lapply(dfList, function(x){colnames(x)=c(name);x})

[[1]]
USAF WBAN YR--MODAHRMN
1    1    2            3

[[2]]
USAF WBAN YR--MODAHRMN
1    1    2            3

1
当然可以,但是你的答案将新数据框存储在res中,而问题似乎要求更改环境中的名称。你的答案与被接受的答案没有实质性的区别,也不比被接受的答案更好。 - Prayag Gordy

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