代码之家  ›  专栏  ›  技术社区  ›  jay.sf

如何向列表中的列表添加列而不丢失其名称?

  •  4
  • jay.sf  · 技术社区  · 7 年前

    我多次尝试向数据帧resp添加特定列。列表中的列表,但所有 *apply() 试图保留数据帧的名称失败。

    l

    l <- list(alpha=data.frame(1:3), bravo=data.frame(4:6), charly=data.frame(7:9))
    
    > l
    $`alpha`
      X1.3
    1    1
    2    2
    3    3
    
    $bravo
      X4.6
    1    4
    2    5
    3    6
    
    $charly
      X7.9
    1    7
    2    8
    3    9
    

    我想把名单上名字的首字母作为第二个字母 id

    lapply(seq_along(l), function(x) cbind(l[[x]], id=substr(names(l)[x], 1, 1)))
    # or
    lapply(seq_along(l), function(x) data.frame(l[[x]], id=substr(names(l)[x], 1, 1)))
    # [[1]]
    # X1.3 id
    # 1    1  a
    # 2    2  a
    # 3    3  a
    # 
    # [[2]]
    # X4.6 id
    # 1    4  b
    # 2    5  b
    # 3    6  b
    # 
    # [[3]]
    # X7.9 id
    # 1    7  c
    # 2    8  c
    # 3    9  c
    

    但内部名单已经失去了它们的名字。选项 USE.NAMES=TRUE lapply() 文件没用。

    lapply(seq_along(l), function(x) mapply(cbind, l[[x]], id=substr(names(l)[x], 1, 1), 
                                            SIMPLIFY=FALSE))
    rapply(l, function(x) cbind(x, id=substr(names(l)[x], 1, 1)), how="list")
    

    我知道我可以这样做:

    l1 <- lapply(seq_along(l), function(x) cbind(l[[x]], id=substr(names(l)[x], 1, 1)))
    names(l1) <- names(l)
    

    或者做一个 for 循环:

    for(i in seq_along(l)) {
      l[[i]] <- data.frame(l[[i]], id=substr(names(l)[i], 1, 1))
    }
    

    但我想知道 *应用() 可以改进解决方案以实现预期产出,即:

    $`alpha`
      X1.3 id
    1    1  a
    2    2  a
    3    3  a
    
    $bravo
      X4.6 id
    1    4  b
    2    5  b
    3    6  b
    
    $charly
      X7.9 id
    1    7  c
    2    8  c
    3    9  c
    
    3 回复  |  直到 7 年前
        1
  •  5
  •   markus    7 年前

    尝试 Map

    Map(`[<-`, l, "id", value = substr(names(l), 1, 1))
    #$alpha
    #  X1.3 id
    #1    1  a
    #2    2  a
    #3    3  a
    
    #$bravo
    #  X4.6 id
    #1    4  b
    #2    5  b
    #3    6  b
    
    #$charly
    #  X7.9 id
    #1    7  c
    #2    8  c
    #3    9  c
    

    第一个参数是一个函数。 地图 ?mapply .

        2
  •  2
  •   G. Grothendieck    7 年前

    sapply simplify = FALSE .

    addId <- function(x) cbind(l[[x]], id = substring(x, 1, 1))
    sapply(names(l), addId, simplify = FALSE)
    

    给:

    $`alpha`
      X1.3 id
    1    1  a
    2    2  a
    3    3  a
    
    $bravo
      X4.6 id
    1    4  b
    2    5  b
    3    6  b
    
    $charly
      X7.9 id
    1    7  c
    2    8  c
    3    9  c
    

    replace(l, TRUE, lapply(names(l), addId))
    
        3
  •  2
  •   camille    7 年前

    如果你不介意切换到 purrr::map 来自美国的家庭 apply 家庭 purrr::imap cbind 调用,但现在可以轻松访问数据帧的名称。

    l <- list(alpha=data.frame(1:3), bravo=data.frame(4:6), charly=data.frame(7:9))
    
    purrr::imap(l, function(df, name) cbind(df, id = substr(name, 1, 1)))
    #> $alpha
    #>   X1.3 id
    #> 1    1  a
    #> 2    2  a
    #> 3    3  a
    #> 
    #> $bravo
    #>   X4.6 id
    #> 1    4  b
    #> 2    5  b
    #> 3    6  b
    #> 
    #> $charly
    #>   X7.9 id
    #> 1    7  c
    #> 2    8  c
    #> 3    9  c
    

    tidyverse ,您可以添加带有 dplyr::mutate 在你的内心 imap .

    library(tidyverse)
    
    imap(l, function(df, name) df %>% mutate(id = str_sub(name, 1, 1)))
    #> $alpha
    #>   X1.3 id
    #> 1    1  a
    #> 2    2  a
    #> 3    3  a
    #> 
    #> $bravo
    #>   X4.6 id
    #> 1    4  b
    #> 2    5  b
    #> 3    6  b
    #> 
    #> $charly
    #>   X7.9 id
    #> 1    7  c
    #> 2    8  c
    #> 3    9  c
    

    正如@markus所指出的,您还可以使用 ~. purrr::imap 他的两个论点变成了 .x (数据帧)和 .y

    purrr::imap(l, ~cbind(.x, id = substr(.y, 1, 1)))