【问题标题】:How do I extract values from uniform list in R?如何从 R 中的统一列表中提取值?
【发布时间】:2011-08-02 03:57:14
【问题描述】:

例如,我如何在下面的列表people 中获取每个人的年龄向量:

> people = vector("list", 5)
> people[[1]] = c(name="Paul", age=23)
> people[[2]] = c(name="Peter", age=35)
> people[[3]] = c(name="Sam", age=20)
> people[[4]] = c(name="Lyle", age=31)
> people[[5]] = c(name="Fred", age=26)
> ages = ???
> ages
[1] 23 35 20 31 26

是否有等效的 Python 列表推导式或具有相同效果的东西?

【问题讨论】:

    标签: r list extract


    【解决方案1】:

    你可以使用sapply:

    > sapply(people, function(x){as.numeric(x[2])})
    [1] 23 35 20 31 26
    

    【讨论】:

    • facepalms 我完全忽略了 *apply 的东西......非常有帮助。谢谢。
    【解决方案2】:

    鉴于您提供的数据结构,我会使用sapply

    sapply(people, function(x) x[2])
    
    > sapply(people, function(x) x[2])
     age  age  age  age  age 
    "23" "35" "20" "31" "26" 
    

    但是,您会注意到其结果是字符数据。

    > class(people[[1]])
    [1] "character"
    

    一种方法是在调用 sapply 时强制使用 as.numeric()as.integer()

    或者 - 如果您一开始就可以灵活地存储数据,则将其存储为data.frames 的列表可能是有意义的:

    people = vector("list", 5)
    people[[1]] = data.frame(name="Paul", age=23)
    people[[2]] = data.frame(name="Peter", age=35)
    ...
    

    如果您打算走那么远,您可能还需要考虑为所有数据使用单个 data.frame:

    people2 <- data.frame(name = c("Paul", "Peter", "Sam", "Lyle", "Fred")
                          , age = c(23,35,20,31, 26))
    

    虽然您第一次没有考虑这种方法,但可能还有其他原因......

    【讨论】:

    • 是的,在这个简单的例子中,数据框可能更好。但“真实”的例子要复杂得多,所以列表更合适。还是谢谢
    • @c00kie - 这就是我的想法,但有时很容易忽略看似显而易见的事情:)
    • +1 关于 R-ish 而不是 Pythonic 数据结构的建议。另外,只是因为我觉得它很漂亮:sapply(people, "[", 2).
    • @joran,“[”在 sapply 调用中有什么作用?我以前看过那个符号,但我真的不记得在哪里......
    • @C00kie - [ 用作索引工具。帮助页面非常有用,其中包含一些很好的信息?'['[[$ 也在那里讨论。
    【解决方案3】:
    ages <- sapply(1:length(people), function(i) as.numeric(people[[i]][[2]]))
    ages
    

    输出:

    [1] 23 35 20 31 26

    【讨论】:

      【解决方案4】:

      除了apply-family,还有@Hadley 的purrr package,它为此类工作提供了map_-function。

      (与讨论的apply-family 有一些不同,例如here。)

      OP 示例:

      people = vector("list", 5)
      people[[1]] = c(name="Paul", age=23)
      people[[2]] = c(name="Peter", age=35)
      people[[3]] = c(name="Sam", age=20)
      people[[4]] = c(name="Lyle", age=31)
      people[[5]] = c(name="Fred", age=26)
      

      sapply 方法:

      ages_sapply <- sapply(people, function(x){as.numeric(x[2])})
      print(ages_sapply)
      [1] 23 35 20 31 26
      

      还有map 方法:

      ages_map <- purrr::map_dbl(people, function(x){as.numeric(x[2])})
      print(ages_map)
      [1] 23 35 20 31 26
      

      当然它们是相同的:

      identical(ages_sapply, ages_map)
      [1] TRUE
      

      【讨论】:

        【解决方案5】:

        虽然这个问题已经很老了,但我还是想分享一下我的解决方法。当然可以使用sapply as tflutre 建议。但我发现使用unlist 函数更直观:

        > ages <- unlist(people, use.names = F)[seq(2, 2 * length(people), 2)]
        > ages
        [1] "23" "35" "20" "31" "26"
        

        注意 2 * length(people) 中的 two 乘法,poeple 列表中存储了两个元素。这可以通过写length(people[[1]]) * length(people)来变得更通用

        这里unlist(people, use.names = F) 产量

        [1] "Paul"  "23"    "Peter" "35"    "Sam"   "20"    "Lyle"  "31"    "Fred" 
        [10] "26" 
        

        然后我们使用seq 命令将其按每个其他元素分割。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-09-02
          • 2021-02-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-07-08
          • 2014-02-13
          相关资源
          最近更新 更多