【问题标题】:Looping over rows of a dataframe conditionally有条件地循环数据帧的行
【发布时间】:2025-12-27 19:30:11
【问题描述】:

我下面的循环结构效果很好。但是,如果我们有:m = data.frame(po = c(1,2,1,2), ou = rep(1,4))input = rev(expand.grid(ou = seq_len(max(m$ou)), po = seq_len(max(m$po)))),并且我希望得到与现在相同的输出(即两个元素的列表),

那么,lapply(input, ... 应该如何变化?

m = list(A = data.frame(po = c(1,2,1,2), ou = rep(1,4)))
# if: `m = data.frame(po = c(1,2,1,2), ou = rep(1,4))`

input <- lapply(m, function(i) rev(expand.grid(ou = seq_len(max(i$ou)),
 po = seq_len(max(i$po)))))

# if: `input = rev(expand.grid(ou = seq_len(max(m$ou)), po = seq_len(max(m$po))))`

lapply(input, function(inp) Map(function(p, o)  ## Then, how should this change?
  do.call(rbind, lapply(m, function(m1)
    m1[m1$po == p & m1$ou == o, , drop = FALSE])), inp$po, inp$ou))

#==== Current & Desired Output:
#$A
#$A[[1]]
    po ou
A.1  1  1
A.3  1  1

#$A[[2]]
    po ou
A.2  2  1
A.4  2  1

【问题讨论】:

  • 我有点困惑你在问什么。需要您更改 lapply 语句的输入更改是什么?
  • 啊哈,在这种情况下,只需将其包装为lapply(list(input), ...)

标签: r function dataframe loops lapply


【解决方案1】:

据我所知,在另一种情况下返回相同输入所需的代码更改最少是将inputm 包装在函数list() 中,以便它们都是列表长度为 1 的单个元素是一个数据框。数据框本身就是列表(数据框的每一列都是列表的一个元素)。因此,如果您不将数据框包装在list() 中,lapply 语句将尝试遍历数据框的列并失败。

m <- data.frame(po = c(1,2,1,2), ou = rep(1,4))

input <- rev(expand.grid(ou = seq_len(max(m2$ou)), po = seq_len(max(m2$po))))

lapply(list(input), function(inp) Map(function(p, o)  ## How should this change?
  do.call(rbind, lapply(list(m), function(m1)
    m1[m1$po == p & m1$ou == o, , drop = FALSE])), inp$po, inp$ou))

【讨论】:

  • 您认为我们可以在输出中减少一级列表吗?所以,我们有new_output = list(data.frame(po=c(1,1),ou=c(1,1)), data.frame(po=c(2,2),ou=c(1,1)))
  • 是的,你可以通过调用unlist(output, recursive = FALSE)将输出“展平”1级
  • 但是没有其他方法可以直接从lapply()Map() 调用中直接获取“扁平化”输出,对吧?
  • vapply() 可能会有一些技巧,但我不确定