【问题标题】:How to make a for loop with two indexes?如何使用两个索引创建一个 for 循环?
【发布时间】:2021-04-21 14:28:53
【问题描述】:

尊敬的 StackOverflow 用户,

我正在努力实现 for 循环。我有一个包含时间列(YMD-HMS 格式)的数据框和另一个包含颗粒物数据的列。此外,我有一个包含开始和停止时刻的数据框;

#TIMEPOINTS log

start <- c(ymd_hms("2020-03-06 19:43:00",
                   "2020-03-06 19:47:00",
                   "2020-03-06 19:53:00",
                   "2020-03-06 20:00:00",
                   "2020-03-06 20:13:00",
                   "2020-03-06 20:22:00",
                   "2020-03-06 20:32:00",
                   "2020-03-06 20:36:00",
                   "2020-03-06 20:42:00",
                   "2020-03-06 20:45:00",
                   "2020-03-06 20:49:00",
                   "2020-03-06 21:01:00",
                   "2020-03-06 21:04:00",
                   "2020-03-06 21:06:00",
                   "2020-03-06 21:09:00",
                   "2020-03-06 21:12:00"))

end <- c(ymd_hms("2020-03-06 19:46:00",
                 "2020-03-06 19:49:00",
                 "2020-03-06 19:55:00",
                 "2020-03-06 20:02:00",
                 "2020-03-06 20:15:00",
                 "2020-03-06 20:24:00",
                 "2020-03-06 20:34:00",
                 "2020-03-06 20:38:00",
                 "2020-03-06 20:44:00",
                 "2020-03-06 20:47:00",
                 "2020-03-06 20:51:00",
                 "2020-03-06 21:03:00",
                 "2020-03-06 21:06:00",
                 "2020-03-06 21:08:00",
                 "2020-03-06 21:11:00",
                 "2020-03-06 21:14:00"))

df <- data.frame(start, end)

我希望创建一个包含所有数据点但没有这些特定时间点的新数据框,就像这样; (但不是使用 forloop,而是遍历各个起点和终点)。

dat2 <- dat %>% .[.[["Time"]] >= df$start[1],] %>%
    .[.[["Time"]] <= df$end[1],]

我知道这可以使用 for 循环来完成,我试图根据我的情况来解决这个问题,但我有点迷茫..

非常感谢任何帮助!

【问题讨论】:

  • 您拥有的解决方案非常好(有点……),实际上比for 循环要好得多。您想在这里使用for 循环的原因是什么?或者是为了排除 所有 次落入您的 df 范围内的时间?
  • 抱歉,我的问题显然不够清楚。事实上,我想排除所有落入这些范围的时间。

标签: r for-loop nested-for-loop


【解决方案1】:

首先,我会稍微清理一下您当前的代码:

dat2 <- dat %>% .[.$Time >= df$start[1] && .$Time <= df$end[1],]

通过使用&amp;&amp;,您将两个子集操作减少为一个。在这种情况下,与 [["…"]] 相比,使用 $… 可以减少混乱。

接下来,我建议将这个条件提取到一个函数中(实际上这个函数已经存在于‘dplyr’包中:between)。这使我们可以将代码编写为

dat2 <- dat %>% filter(between(Time, df$start[1], df$end[1]))

现在我们要对其进行矢量化以检查与 any 间隔的重叠:

dat2 <- dat %>% filter(between_any(Time, df$start, df$end))

现在我们需要编写between_any 函数。让我们首先为 single 查询值实现它:

between_any1 = function (x, left, right) {
    any(x >= left & x <=  right)
}

注意这里使用&amp;,而不是&amp;&amp;;这是因为我们在leftright矢量化,而&amp;&amp;&amp; 的矢量化版本。也就是说,4 &gt;= (1 : 3) &amp; 4 &lt;= (3 : 5) 的结果是 c(FALSE, TRUE, TRUE)

现在我们需要在x 是一个向量时进行这项工作。我们可以使用基本 R 函数Vectorize,但我通常觉得手动完成会更好:

between_any = function (x, left, right) {
    map_lgl(x, ~ any(.x >= left & .x <= right))
}

这使用了“purrr”,但我们也可以使用lapplyvapply

哦,听起来您想过滤掉次落入df范围内的时间,因此您需要反转filter的条件:

dat2 <- dat %>% filter(! between_any(Time, df$from, df$to))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-10-31
    • 2021-07-25
    • 2016-01-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-01
    相关资源
    最近更新 更多