更改R

时间:2018-06-08 16:38:52

标签: r list dataframe rename lapply

此问题是Changing Column Names in a List of Data Frames in R的扩展名。

该帖子解决了更改data.frame的所有列的名称的问题。

但是,如何仅更改选定数量的列的名称?

示例:

我想仅在列表中的每个data.frame中更改第一列的名称:

dat <- data.frame(Foo = 1:5,Bar = 1:5)
lst <- list(dat,dat)

print(lst)

[[1]]
  Foo Bar
1   1   1
2   2   2
3   3   3
4   4   4
5   5   5

[[2]]
  Foo Bar
1   1   1
2   2   2
3   3   3
4   4   4
5   5   5

(失败)尝试:

lapply(1:2, function(x) names(lst[[x]])[names(lst[[x]]) == 'Foo'] <- 'New')
lapply(1:2, function(x) names(lst[[x]])[names(lst[[x]]) == 'Foo'])  <- rep('New',2)
lapply(1:2, function(x) setNames(lst[[x]][names(lst[[x]]) == 'Foo'],'New'))

6 个答案:

答案 0 :(得分:5)

以下是使用setNamesgsub的一种可能性:

# Sample data
dat <- data.frame(Foo = 1:5,Bar = 1:5)
lst <- list(dat,dat[, 2:1])

# Replace Foo with FooFoo
lst <- lapply(lst, function(x) setNames(x, gsub("^Foo$", "FooFoo", names(x))) )
#[[1]]
#  FooFoo Bar
#1      1   1
#2      2   2
#3      3   3
#4      4   4
#5      5   5
#
#[[2]]
#  Bar FooFoo
#1   1      1
#2   2      2
#3   3      3
#4   4      4
#5   5      5

答案 1 :(得分:4)

您尝试的两个问题:

  1. 使用lapply(1:2, ...)代替lapply(lst, ...)很奇怪。这使你的匿名功能更加尴尬。

  2. 您的匿名函数不会return数据框。返回函数的最后一行(没有return()语句)。在您第一次尝试时,最后一行的值只是指定的值"new" - 我们需要使用修改后的名称返回整个数据框。

  3. 解决方案:

    lapply(lst, function(x) {names(x)[names(x) == 'Foo'] <- 'New'; x})
    # [[1]]
    #   New Bar
    # 1   1   1
    # 2   2   2
    # 3   3   3
    # 4   4   4
    # 5   5   5
    # 
    # [[2]]
    #   New Bar
    # 1   1   1
    # 2   2   2
    # 3   3   3
    # 4   4   4
    # 5   5   5
    

答案 2 :(得分:1)

以下是按列索引更改列名称的方法。

lapply(lst, function(x, pos = 1, newname = "New"){
  # x: data frame, pos: column index, newname: new name of the column
  column <- names(x)
  column[pos] <- newname
  names(x) <- column
  return(x)
})
# [[1]]
#   New Bar
# 1   1   1
# 2   2   2
# 3   3   3
# 4   4   4
# 5   5   5
# 
# [[2]]
#   New Bar
# 1   1   1
# 2   2   2
# 3   3   3
# 4   4   4
# 5   5   5

我在发布OP的更新评论之前发布了这个答案,说明每个数据框的目标列的索引可能不同。原帖中没有提到这一点。请看其他人&#39;发布,因为我的答案仅在列索引一致时才有效。

答案 3 :(得分:1)

我的解决方案比其他解决方案更复杂,但在这里。

主要区别在于==代替grep使用ignore.case = TRUE(带参数lapply(lst, function(DF) { inx <- grep("^foo$", names(DF), ignore.case = TRUE) names(DF)[inx] <- "New" DF }) #[[1]] # New Bar #1 1 1 #2 2 2 #3 3 3 #4 4 4 #5 5 5 # #[[2]] # New Bar #1 1 1 #2 2 2 #3 3 3 #4 4 4 #5 5 5 )。

{{1}}

答案 4 :(得分:1)

使用tidyverse

library(tidyverse)
map(lst,rename_at,"Foo",~"New")
# [[1]]
# New Bar
# 1   1   1
# 2   2   2
# 3   3   3
# 4   4   4
# 5   5   5
# 
# [[2]]
# New Bar
# 1   1   1
# 2   2   2
# 3   3   3
# 4   4   4
# 5   5   5

使用data.table

library(data.table)
lst2 <- copy(lst)
lapply(lst2,setnames,"Foo","New")

# [[1]]
# New Bar
# 1   1   1
# 2   2   2
# 3   3   3
# 4   4   4
# 5   5   5
# 
# [[2]]
# New Bar
# 1   1   1
# 2   2   2
# 3   3   3
# 4   4   4
# 5   5   5

此处通过引用进行更改,因此我们先制作副本。

答案 5 :(得分:0)

注意没有赋值,它不会更改原始对象。

lst <- purrr::map(lst, ~setNames(.x, c('new', names(.x)[-1])))