【问题标题】:Conditional addition or row to dataframe based on time根据时间对数据框进行条件添加或行
【发布时间】:2020-10-12 10:38:14
【问题描述】:

我需要从现有数据框创建一个汇总数据框,这是当前数据框的示例:

df1 = data.frame(datetime = as.POSIXct(c("2019-04-11 21:46:55",
                                         "2019-04-13 00:19:23",
                                         "2019-04-15 01:20:41",
                                         "2019-04-15 04:18:12",
                                         "2019-04-24 05:54:17",
                                         "2019-04-22 08:44:41",
                                         "2019-04-23 03:49:31",
                                         "2019-04-23 03:45:21",
                                         "2019-04-23 00:50:45",
                                         "2019-04-22 09:16:08",
                                         "2019-04-23 07:21:36",
                                         "2019-04-23 07:24:53")), order = c(1,3,4,5,9,7,6,6,6,7,7,7))

函数/循环需要返回等于length(unique(order) 的行,在本例中为 7 行。最终我将计算行之间的时间差,所以我总是需要每一行在时间上是连续的(产生正值)。如果当前行的datetime 在前一行之前,则需要进行条件检查,拒绝添加该行并选择在前一个datetime 时间之后存在的第一行。

在上面的例子中order 7 有三行。对于这个order,应该返回的行是2019-04-23 07:21:36 7,因为订单6 的日期时间为2019-04-23 00:50:45,因此2019-04-22 08:44:41 将在前一行的datetime 之前,这是不可能发生的,因此会被拒绝.

重要的是,函数/循环不应该只找到日期时间在前一行之后的任何行,而应该是满足此条件的第一个可能行(因此在上述情况下,"2019-04-23 07:20:00" 应该被丢弃以及)。所以我不能使用类似df1 %>% arrange(datetime) %>% group_by(order) %>% slice_max(1)

输出应该是这样的:

new.df = data.frame(datetime = as.POSIXct(c("2019-04-11 21:46:55",
                                            "2019-04-13 00:19:23",
                                            "2019-04-15 01:20:41",
                                            "2019-04-15 04:18:12",
                                            "2019-04-23 00:50:45",
                                            "2019-04-23 07:21:36",
                                            "2019-04-24 05:54:17")), order = c(1,3,4,5,6,7,9))

干杯

【问题讨论】:

  • filter(df1, order >= cummax(order)) 工作吗?
  • 我不这么认为。它适用于上面的小例子,但不适用于我的大 df。我不确定为什么。不幸的是我不能重复 df 因为它太大了......但基本上每个日期时间/订单组合都有数千行......我只需要返回length(unique(order))。通常为 13 行或更少。
  • 重读后我认为dplyr::filter(df1, order > cummax(dplyr::lag(order, default = -1))) 会更好。
  • 似乎很接近。但它并没有将所有不同的order 行放在一起。即假设应该有 7 行,它只返回 6。当我检查 df %>% distinct(order) 时,有 7 个唯一值
  • 我不完全理解你的问题。您能否创建一个包含所有边缘情况以及预期输出的最小示例?您在寻找longest increasing subsequence 吗?如果所有订单 7 都在订单 6 之前呢?

标签: r loops dplyr


【解决方案1】:

这可能不是最简单的解决方案,但它确实适用于您的示例。

首先,我们按日期排序并过滤相同order 的条纹,只保留第一个。这会丢弃第二个和第三个6 以及第三个和第四个7。
然后,我们按日期反向排序并应用我之前作为评论提出的过滤器,但使用cummin,从而确保我们只保留少于任何前一行的行。这抛弃了第一个 7。
然后,我们再次按日期排序,得到最终输出。

library(dplyr)

df1 %>%
  arrange(datetime) %>% 
  filter(order != lag(order, default = Inf)) %>% 
  arrange(desc(datetime)) %>% 
  filter(order <= cummin(order)) %>% 
  arrange(datetime)

这给了

             datetime order
1 2019-04-11 21:46:55     1
2 2019-04-13 00:19:23     3
3 2019-04-15 01:20:41     4
4 2019-04-15 04:18:12     5
5 2019-04-23 00:50:45     6
6 2019-04-23 07:21:36     7
7 2019-04-24 05:54:17     9

【讨论】:

  • 谢谢。这似乎有效。我们将看看我是否可以将它应用到我拥有的一堆数据帧上,而不会出现任何其他问题!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-06-18
  • 2021-06-20
  • 1970-01-01
  • 2023-02-10
  • 2011-08-13
  • 2016-09-10
  • 2022-06-18
相关资源
最近更新 更多