【问题标题】:Sort nested lists in r在r中对嵌套列表进行排序
【发布时间】:2014-12-04 20:58:23
【问题描述】:

我有几个列表,每个列表都有 N 个对象(例如下面的 unsorted$b)和一个包含 N 行的数据框(下面的 unsorted$a)。所有这些都在一个列表中 (unsorted)。我希望对数据框进行排序,同时重新排列每个嵌套列表以保留一般顺序。例如:

> unsorted <- list(a=data.frame(age=c(30,10,20), name=c("ann","bob","carl")), b=list("3x10","1x10","2x10"))
> unsorted
$a
  age name
1  30  ann
2  10  bob
3  20 carl

$b
$b[[1]]
[1] "3x10"

$b[[2]]
[1] "1x10"

$b[[3]]
[1] "2x10"

我想按年龄排序

ord <- order(unsorted$a$age)

这就是诀窍:

sorted <- list(a=unsorted$a[ord,], b=unsorted$b[ord])
> sorted
$a
  age name
2  10  bob
3  20 carl
1  30  ann

$b
$b[[1]]
[1] "1x10"

$b[[2]]
[1] "2x10"

$b[[3]]
[1] "3x10"

这可以通过 apply 或其化身之一来完成吗?

-- 编辑--

我真实案例中的父列表有大量的子列表。所有子列表都包含 N 个对象,但这些对象具有可变结构。

【问题讨论】:

  • 查看我的编辑。下次尝试在您的文本和代码中引用您的变量名。如果您的第一段说“我有几个列表,每个列表都有 N 个对象(例如下面的unsorted$b)和一个包含 N 行的数据框(下面的unsorted$a),那么您的第一段将立即对我有意义。所有这些都在一个单个列表 (unsorted)...
  • 当然,现在我很清楚,但在第一次阅读时,我认为您的意思是 每个 列表都有自己的 data.frame,但不必猜测哪个在您的示例中列出您的意思是“所有这些都分组在数据框和嵌套列表的列表中”会让我更快地直截了当。

标签: r list sorting


【解决方案1】:

如果我正确理解了您的数据结构,那么您有一个包含这些子列表的大列表,如下所示:

list_of_lists = list(unsorted, unsorted)

您在问题中只给出了一个示例子列表,所以我假设

  • 你确实有一个像这样的大列表
  • 有 1 级嵌套,即您的子列表不可能包含更多需要排序的子列表,并且
  • 您的所有子列表都恰好有 1 个数据框,并且它有一个名为“年龄”的列来确定排序。

编写进行排序的函数:

sort_list <- function(x) {
    df.index <- which(sapply(x, is.data.frame))
    stopifnot(length(df.index) == 1)
    ord <- order(x[[df.index]]$age)
    lapply(x, FUN = function(y) {
        if (is.data.frame(y)) return(y[ord, ])
        return(y[ord])
    }
    )
}

然后lapply 将它添加到您的列表列表中:

lapply(list_of_lists, sort_list)

编辑:

现在你已经澄清了你的数据结构,我认为要做的事情是先得到订单,然后lapply对所有东西排序。

# Using your code to get the order:
ord <- order(unsorted$a$age)

lapply(unsorted, function(x, ord) {
      if (is.data.frame(x)) return(x[ord,])
      return(x[ord])
    },
    ord = ord
)

【讨论】:

  • 谢谢@Gregor。大列表有数据框和大量的N长列表,所有这些都需要在内部重新排序。我的示例通过仅考虑此类子列表之一进行了简化。
  • 将@Gregor 的解决方案应用于我的案例(在最后一条评论中描述)返回空子列表。需要在代码中进行一些调整
  • 哦,听起来每个子列表都有一个数据框。所以听起来你的例子不是一个子列表,而是大列表的一个小例子。 (这意味着它是一个更好的例子。)它也容易得多,我今天晚些时候有时间再编辑。
【解决方案2】:

你可以使用

lapply(unsorted, function(x) {
    if(is.vector(x)) x[order(unlist(x))] else x[order(x$age),]
})

$a
  age name
2  10  bob
3  20 carl
1  30  ann

$b
$b[[1]]
[1] "1x10"

$b[[2]]
[1] "2x10"

$b[[3]]
[1] "3x10"

【讨论】:

  • 比我的答案做出更多假设,但更清晰(+1)。
  • 谢谢。尝试将这一点推广到所有可能的数据结构会很长。
  • 感谢@RichardScriven。正如我上面评论的那样,我的大列表包括数据框和大量 N 长度列表(具有可变结构的对象)。所有子列表都需要使用与数据框相同的标准重新排序。
猜你喜欢
  • 2014-08-03
  • 2013-02-06
  • 1970-01-01
  • 2010-09-21
  • 2022-01-14
  • 1970-01-01
  • 2022-01-14
相关资源
最近更新 更多