【问题标题】:How to select all id's rows where all sequence is present?如何选择存在所有序列的所有 id 行?
【发布时间】:2020-06-23 06:05:03
【问题描述】:

我有一个如下的数据表:

DT1 <- data.table(
  id=c(1,1,1,2,2,2,1,1),
  sensor_id=c(1,2,3,1,2,3,2,3),
  time=c("2017-01-01 00:00:05","2017-01-01 00:06:35","2017-01-01 00:23:44","2017-01-02 22:00:20","2017-01-02 22:01:09","2017-01-02 22:28:02","2017-01-03 22:23:01","2017-01-03 22:50:52")
  )

在这种情况下,我想选择所有具有传感器 ID (1,2,3) 序列的所有 customer_id 行。

所以我想像下面这样标记它们:

DT1 <- data.table(
  id=c(1,1,1,2,2,2,1,1),
  sensor_id=c(1,2,3,1,2,3,2,3),
  time=c("2017-01-01 00:00:05","2017-01-01 00:06:35","2017-01-01 00:23:44","2017-01-02 22:00:20","2017-01-02 22:01:09","2017-01-02 22:28:02","2017-01-03 22:23:01","2017-01-03 22:50:52"),
  group=c(1,1,1,2,2,2,3,3),
  seq_boolean=c(1,1,1,1,1,1,0,0)
)

我可以识别该行是否具有所有序列。 一个id可以出现多次,也不是所有的序列。

为此,我尝试了以下先分组

DT1[,group:=rleid(id),by=list(id,rleid(sensor_id))]

但这只是将所有内容组合为一个。我不确定我在哪里做错了。任何帮助表示赞赏。

编辑 我也可以有如下格式的数据表。

DT1 <- data.table(
       id=c(1,2,1,2,1,2,1,1),
       sensor_id=c(1,1,2,2,3,3,2,3),
       time=c("2017-01-01 00:00:05","2017-01-01 00:06:35","2017-01-01 00:23:44","2017-01-02 00:00:20","2017-01-02 00:35:09","2017-01-02 00:28:02","2017-01-03 00:45:01","2017-01-03 00:50:52")
   )

这里的组由 sensor_id 定义。sensor_id 1 是会话的开始,sensor_id 2 是中间会话,sensor_id 3 是会话的结束。一个 id 可以有多个会话,并且某些传感器可能无法捕获该 id。所以我的目的是识别所有 3 个传感器 ID 捕获的所有会话,并查看捕获了多少。

【问题讨论】:

  • 对于您的 EDIT 数据,我的回答仍然给出了预期的输出,对吗?
  • 抱歉再次编辑错误。我试图包含的测试用例是传感器 1 是开始,传感器 3 是 id 会话的结束。但有些可能从传感器 2 开始并以 3 结束。所以需要识别(分组列进行计数)并删除它们是我的目的。
  • 我认为这个例子仍然不准确,因为我的原始答案仍然适用于此,但我想我现在理解你了。你能检查我编辑的答案吗?
  • 非常抱歉,复制时出现问题。我认为我们不能简单地将其按 rleid 分组为 id。需要标识 start 和 end 对吗?
  • 你想在有 3 的时候开始一个新的会话吗?也许像DT1[, g := shift(cumsum(sensor_id==3L), fill=0L), id][, group := .GRP, .(id, g)]

标签: r dplyr data.table


【解决方案1】:

我们可以检查每个组是否存在所有uniq_sensor

uniq_sensor <- unique(DT1$sensor_id)
DT1[, seq_boolean := +(all(uniq_sensor %in% sensor_id)), rleid(id)]
DT1

#   id sensor_id                time seq_boolean
#1:  1         1 2017-01-01 00:00:05           1
#2:  1         2 2017-01-01 00:06:35           1
#3:  1         3 2017-01-01 00:23:44           1
#4:  2         1 2017-01-02 22:00:20           1
#5:  2         2 2017-01-02 22:01:09           1
#6:  2         3 2017-01-02 22:28:02           1
#7:  1         2 2017-01-03 22:23:01           0
#8:  1         3 2017-01-03 22:50:52           0

我们还可以计算每个组的唯一传感器的长度:

DT1[, seq_boolean := +(uniqueN(sensor_id) == length(uniq_sensor)), rleid(id)]

编辑

对于我们要确保sensor_id 以完全相同的顺序出现的其他条件,我们可以这样做:

library(dplyr)

DT1 %>%
  group_by(id) %>%
  group_by(grp = cumsum(c(TRUE, diff(sensor_id) <= 0)), .add = TRUE) %>%
  #Use add = TRUE for old dplyr < 1.0.0
  mutate(seq_boolean = +(all(uniq_sensor %in% sensor_id)))

【讨论】:

  • 谢谢,对 all 函数的介绍。是的,但是还有一种方法可以创建组列。我试图先创建它,然后再创建 seq_boolean。
  • @Ricky 先做DT1[, group := rleid(id)] 然后在上面的答案中使用group
  • 是的,我试过了,但这仅在数据表采用给定格式时才有效。有时我有数据表,如果我申请DT1=DT1[order(time)],那么这将不起作用。在那些情况下,我该如何转换成这个,因为DT1[order(id,time)] 这个不产生上述格式。
  • 对不起,我不明白。 DT1 已经按time 排序,所以我认为DT1=DT1[order(time)] 没有任何变化。
【解决方案2】:
DT1[,seq_boolean := +setequal(sensor_id, DT1[, sensor_id]), by = rleid(id)]
DT1
   id sensor_id                time seq_boolean
1:  1         1 2017-01-01 00:00:05           1
2:  1         2 2017-01-01 00:06:35           1
3:  1         3 2017-01-01 00:23:44           1
4:  2         1 2017-01-02 22:00:20           1
5:  2         2 2017-01-02 22:01:09           1
6:  2         3 2017-01-02 22:28:02           1
7:  1         2 2017-01-03 22:23:01           0
8:  1         3 2017-01-03 22:50:52           0

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-03-23
    • 2016-06-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-02
    • 2019-12-19
    相关资源
    最近更新 更多