【问题标题】:Multiple list nesting with split(), R使用 split() 嵌套多个列表,R
【发布时间】:2019-03-16 22:35:00
【问题描述】:

给定一个数据集在一列中有多个唯一元素,我想将这些唯一元素拆分为新的数据框,但让数据框向下嵌套一层。本质上为split() 命令添加了一个额外的级别。

例如(以内置的iris 表为例:

iris
mylist <- split(iris, iris$Species)

产生一个列表mylist,其中包含3个子列表setosaversicolorvirginica

mylist[["setosa"]]

       Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1           5.1         3.5          1.4         0.2  setosa
2           4.9         3.0          1.4         0.2  setosa
3           4.7         3.2          1.3         0.2  setosa
4           4.6         3.1          1.5         0.2  setosa
5           5.0         3.6          1.4         0.2  setosa

但我实际上想将该数据表嵌套在名为results 的子列表中,但将上层列表名称保留为setosa。这样:

mylist$setosa["results"]

  Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1           5.1         3.5          1.4         0.2  setosa
2           4.9         3.0          1.4         0.2  setosa
3           4.7         3.2          1.3         0.2  setosa
4           4.6         3.1          1.5         0.2  setosa
5           5.0         3.6          1.4         0.2  setosa

我可以通过手动操作来做到这一点,但我希望它自动运行。我用mapply尝试失败了

mapply(function(names, df) 
   names <- split(df, df[["Species"]]), 
   unique(iris$Species), iris)

有什么建议吗?如果这能让事情变得更容易,也很高兴使用tidyr 包......

【问题讨论】:

  • dplyr::group_by(iris, Species) %&gt;% tidyr::nest() %&gt;% %&gt;% { set_names(.$data, .$Species) } ; split(iris, iris$Species) %&gt;% as.list()

标签: r list nested lapply mapply


【解决方案1】:

考虑bytapply 的面向对象包装器),与split 非常相似,但允许您在每个子集上运行一个函数。很多用户经常运行split + lapply,不知道两者都可以替换为by

mylist <- by(iris, iris$Species, function(sub) list(results=sub), simplify = FALSE)

head(mylist$setosa$results)
#   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
# 1          5.1         3.5          1.4         0.2  setosa
# 2          4.9         3.0          1.4         0.2  setosa
# 3          4.7         3.2          1.3         0.2  setosa
# 4          4.6         3.1          1.5         0.2  setosa
# 5          5.0         3.6          1.4         0.2  setosa
# 6          5.4         3.9          1.7         0.4  setosa

head(mylist$versicolor$results)
#    Sepal.Length Sepal.Width Petal.Length Petal.Width    Species
# 51          7.0         3.2          4.7         1.4 versicolor
# 52          6.4         3.2          4.5         1.5 versicolor
# 53          6.9         3.1          4.9         1.5 versicolor
# 54          5.5         2.3          4.0         1.3 versicolor
# 55          6.5         2.8          4.6         1.5 versicolor
# 56          5.7         2.8          4.5         1.3 versicolor

head(mylist$virginica$results)
#     Sepal.Length Sepal.Width Petal.Length Petal.Width   Species
# 101          6.3         3.3          6.0         2.5 virginica
# 102          5.8         2.7          5.1         1.9 virginica
# 103          7.1         3.0          5.9         2.1 virginica
# 104          6.3         2.9          5.6         1.8 virginica
# 105          6.5         3.0          5.8         2.2 virginica
# 106          7.6         3.0          6.6         2.1 virginica

【讨论】:

  • 这是完美的。甚至不知道“by”。谢谢!!
  • 很高兴听到!确实by 我发现是一种未充分利用的方法。
【解决方案2】:

lapply 中的setNames 将保留您正在迭代的列表的名称

iris
mylist <- split(iris, iris$Species)
mylist2 <- lapply(setNames(names(mylist), names(mylist)), function(x){
  list(results = mylist[[x]])
})

【讨论】:

  • 有效,但使用上面更简单的“by”解决方案。谢谢!
猜你喜欢
  • 2020-11-26
  • 1970-01-01
  • 1970-01-01
  • 2022-01-18
  • 2020-10-29
  • 1970-01-01
  • 2018-11-17
  • 2018-08-16
  • 2023-04-06
相关资源
最近更新 更多