【问题标题】:Deleting all rows within a group that follow the first occurrence of multiple levels of a factor variable in R删除组中在 R 中第一次出现多个因子变量水平之后的所有行
【发布时间】:2021-10-15 01:54:55
【问题描述】:

我的数据每个 id 有多个观察值,并按日期顺序排列。我希望能够删除在每个 id 中第一次出现一个因子之后出现的所有行。在下面的示例中称为“ind”的因子具有多个级别。大多数行将是“a”级。在下面的示例中,我想保留所有行直到出现“b”或“c”,并删除第一次出现这些值中的一个或两个之后的所有行。在某些情况下,“b”和“c”出现在同一个 id 中,并且在完全相同的日期和时间(如下面的示例中的 id=3 所示)。在这种情况下,我想保留具有“b”和“c”的行,而不是简单地删除后面的任何行,无论哪个值先出现。有时 id 没有“b”或“c”值,在这种情况下,我想保留该 id 的所有行。有时一个 id 只有一个“b”和/或“c”值而没有“a”值,在这种情况下,我也会保留所有行,只要它们具有相同的日期和时间,如果同时存在“b”和“c”值。 这是示例数据集的代码:

id <- c(1,1,1,2,2,3,3,3,3,3,4,5,6,6)
ind <- c("a","b","a","a","c","a","a","b","c","a","a","b","a","a")
dt <- c("2017-06-30 00:00:00", "2017-07-1 00:00:00", "2017-07-04 00:00:00",
    "2017-05-23 00:00:00", "2017-05-30 00:00:00",
    "2017-08-04 00:00:00", "2017-08-07 00:00:00", "2017-08-10 00:00:00", "2017-08-10 00:00:00", "2017-08-15 00:00:00",
    "2017-06-05 00:00:00",
    "2017-06-21 00:00:00",
    "2017-01-20 00:00:00", "2017-01-21 00:00:00")
dat <- cbind(id,ind,dt)
dat <- data.frame(dat)
dat$id <- factor(dat$id)
dat$ind <- factor(dat$ind)
dat$dt <- as.POSIXct(dat$dt,tz="America/Chicago",format="%Y-%m-%d %H:%M:%OS")
dat

我想得到一个这样的数据集(id=1的最后一行,id=3的最后一行被删除了):

id <- c(1,1,2,2,3,3,3,3,4,5,6,6)
ind <- c("a","b","a","c","a","a","b","c","a","b","a","a")
dt <- c("2017-06-30 00:00:00", "2017-07-1 00:00:00",
    "2017-05-23 00:00:00", "2017-05-30 00:00:00",
    "2017-08-04 00:00:00", "2017-08-07 00:00:00", "2017-08-10 00:00:00", "2017-08-10 00:00:00",
    "2017-06-05 00:00:00",
    "2017-06-21 00:00:00",
    "2017-01-20 00:00:00", "2017-01-21 00:00:00")
dat2 <- cbind(id,ind,dt)
dat2 <- data.frame(dat2)
dat2$id <- factor(dat2$id)
dat2$ind <- factor(dat2$ind)
dat2$dt <- as.POSIXct(dat2$dt,tz="America/Chicago",format="%Y-%m-%d %H:%M:%OS")
dat2

如果因子中只有两个级别,或者如果 id 有时在同一日期/时间没有超过一个因子级别,那么我可以简单地执行以下操作:

dat %>% group_by(id) %>% arrange(dt, .by_group = TRUE) %>% filter(cumsum(cumsum(ind == "b")) <= 1)

正如question 中所建议的那样。 但是,这在我的情况下不起作用,因为在上面的 id=3 示例中,它只会采用非“a”值行之一。

感谢您的帮助!

【问题讨论】:

  • 已修复,谢谢。不知何故,它掉了下来。也许我没有正确使用代码块引号

标签: r dplyr


【解决方案1】:

我们arrange将数据按'id','dt',按'id'分组,用ind列得到一个向量(c("b", "c"))的match的索引的max ,用NAna_if)替换0,用行数(n())做一个coalesce,用row_number()创建一个逻辑向量到filter行数

library(dplyr)
dat %>% 
    arrange(id, dt) %>% 
    group_by(id) %>% 
    filter(row_number() <= coalesce(na_if(max(match(c("b", "c"), 
           ind, nomatch = 0)), 0), n())) %>%
    ungroup

-输出

# A tibble: 12 × 3
   id    ind   dt                 
   <fct> <fct> <dttm>             
 1 1     a     2017-06-30 00:00:00
 2 1     b     2017-07-01 00:00:00
 3 2     a     2017-05-23 00:00:00
 4 2     c     2017-05-30 00:00:00
 5 3     a     2017-08-04 00:00:00
 6 3     a     2017-08-07 00:00:00
 7 3     b     2017-08-10 00:00:00
 8 3     c     2017-08-10 00:00:00
 9 4     a     2017-06-05 00:00:00
10 5     b     2017-06-21 00:00:00
11 6     a     2017-01-20 00:00:00
12 6     a     2017-01-21 00:00:00

【讨论】:

  • 哇!非常感谢!我不会想出来的。我已经在这上面花了很多时间。非常感谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多