使用数据框的名称重命名数据框列表中的第二列(deparse,substitute和lapply)

时间:2017-09-27 21:20:05

标签: r list dataframe rename lapply

示例数据

我有一个数据框列表,每个数据框有两列:1。变量名,2。整数。

df3 <- df2 <- df1 <- data.frame(Variable = LETTERS[1:5], Value = sample(10:20, 5, replace = TRUE))
df.list <- list(df1 = df1, df2 = df2, df3 = df3)
df.list

# $df1
#     Variable Value
# 1        A    17
# 2        B    16
# 3        C    16
# 4        D    18
# 5        E    10
#
# $df2
#     Variable Value
# 1        A    17
# ...

我想做什么

列表中的每个数据框都已命名。我想提取数据框的名称,并使用它来重命名该数据框中的第二列:

# $df1
#     Variable df1
# 1        A    17
# 2        B    16
# 3        C    16
# 4        D    18
# 5        E    10
#
# $df2
#     Variable df2
# 1        A    17
# ... 

我尝试过的事情

我已经使用deparse(substitute()编写了一个函数来执行此操作,并通过sub()编写正则表达式模式匹配:

mod.name <- function(x) {
    nx <- deparse(substitute(x))
    ny <- sub(".*\\$", "", nx)
    names(x)[2] <- ny
    x
}

在列表中的单个数据框架上进行测试时,它可以工作:

mod.name(df.list$df3)
df.list$df3

# Variable df3
# 1  A     17
# 2  B     16
# 3  C     16
# 4  D     18
# 5  E     10

但是,当使用lapply对列表中的所有数据框执行此操作时,它不会:

lapply(df.list, mod.name)
df.list

# $df1
#    Variable  X[[i]]
# 1        A     17
# 2        B     16
# 3        C     16
# 4        D     18
# 5        E     10
#
# $df2
#    Variable  X[[i]]
# 1        A    17
# ...

当然,之前在StackOverflow上讨论过将deparse(substitute()lapply()一起使用的问题,但我无法获得任何解决方案hereherehere为我工作。

2 个答案:

答案 0 :(得分:2)

您不需要deparse(substitute(.))

nms <- setNames(, names(df.list))
df.list2 <- lapply(nms, function(x){
        names(df.list[[x]])[2] <- x
        df.list[[x]]
    })
df.list2

修改
在下面的评论中提到Frank后,我已将nms <- names(df.list)更改为nms <- setNames(, names(df.list)),并将输出列表的名称更改为df.list2

答案 1 :(得分:2)

从技术上讲,这符合既定目标:

Map(function(x,y){ names(y)[[2]] <- x; y }, names(df.list), df.list)

OP表示他们最终的目标是cbind列在一起(大概是因为Variable列在所有表中都是相同的),所以这里有一些其他的想法。

rbind并重新塑造。要实现这一目标,如果所有变量属于同一类型(例如,整数或浮点数),我只会以长格式存储数据:< / p>

library(data.table)
DT = rbindlist(df.list, id = "src")

    src Variable Value
 1: df1        A    17
 2: df1        B    11
 3: df1        C    20
 4: df1        D    10
 5: df1        E    19
 6: df2        A    17
 7: df2        B    11
 8: df2        C    20
 9: df2        D    10
10: df2        E    19
11: df3        A    17
12: df3        B    11
13: df3        C    20
14: df3        D    10
15: df3        E    19

从那里,您可以使用

返回宽屏格式
dcast(DT, Variable ~ src)

   Variable df1 df2 df3
1:        A  17  17  17
2:        B  11  11  11
3:        C  20  20  20
4:        D  10  10  10
5:        E  19  19  19

cbind如果列的类型不同,可以将它们放在一起

as.data.table(c(df.list[[1]][1], lapply(df.list, `[`, -1)))

   Variable df1.Value df2.Value df3.Value
1:        A        17        17        17
2:        B        11        11        11
3:        C        20        20        20
4:        D        10        10        10
5:        E        19        19        19

如果您正在使用这样的data.table,则可以使用setnames来更改列名。

OP在评论中提到了这两个想法。我只是说明了代码细节。

无论哪种方式,我认为坚持使用一个表格将更容易进行后续分析。