【问题标题】:Delete rows with redundant information in r (not just duplicates)删除 r 中具有冗余信息的行(不仅仅是重复)
【发布时间】:2021-08-24 01:42:14
【问题描述】:

在此示例数据中:

id<-c(2,2,2,2,2,3,3,3,3,3,3,4,4,4,4)
time<-c(3,5,7,8,9,2,8,10,12,14,18,4,6,7,9)
status<-c('mar','mar','div','c','mar','mar','div','mar','mar','c','div','mar','mar','c','mar')

myd<-data.frame(id,time,status)

   id time status
1   2    3    mar
2   2    5    mar
3   2    7    div
4   2    8      c
5   2    9    mar
6   3    2    mar
7   3    8    div
8   3   10    mar
9   3   12    mar
10  3   14      c
11  3   18    div
12  4    4    mar
13  4    6    mar
14  4    7      c
15  4    9    mar

我需要知道这个人什么时候结婚(如果有两个连续的 'mar' 行,中间没有 'div',那么这个人从未离婚,因此它是同一个婚姻,我们不需要那个时间重复信息;mar, c, mar的序列也是如此,由于没有检测到div,因此child前后的婚姻是同一个婚姻,因此可以删除第二个)。我怀疑我需要得到 min(time[status=='mar']) 但如果那个人得到一个 mar,mar,div,mar,div,mar 序列,这将是不正确的(只有 2nd mar 需要删除,而不是所有第一个之后的)。

所以新数据应该看起来像

   id time status
2   2    5    mar
3   2    7    div
4   2    8      c
5   2    9    mar
6   3    2    mar
7   3    8    div
8   3   10    mar
10  3   14      c
11  3   18    div
13  4    6    mar
14  4    7      c

这是我的方法,只适用于一行

myd2<-myd %>% 
  group_by(id) %>% 
  mutate(dum1=ifelse(status=='mar',min(time[status=='mar']),NA),
         dum2=cumsum(status=='div'),
         flag=ifelse(time>dum1 & dum2==0,1,0))

如果我去掉了 dum2==0 那么它删除了太多行。

【问题讨论】:

    标签: r data.table tidyverse


    【解决方案1】:

    使用快速帮助函数,

    func <- function(x, vals = c("mar", "div")) {
      out <- rep(TRUE, length(x))
      last <- x[1]
      for (ind in seq_along(x)[-1]) {
        out[ind] <- x[ind] != last || !x[ind] %in% vals
        if (out[ind] && x[ind] %in% vals) last <- x[ind]
      }
      out
    }
    

    我们可以的

    library(data.table)
    as.data.table(myd)[, .SD[func(status),], by = .(id)]
    #        id  time status
    #     <num> <num> <char>
    #  1:     2     3    mar
    #  2:     2     7    div
    #  3:     2     8      c
    #  4:     2     9    mar
    #  5:     3     2    mar
    #  6:     3     8    div
    #  7:     3    10    mar
    #  8:     3    14      c
    #  9:     3    18    div
    # 10:     4     4    mar
    # 11:     4     7      c
    

    如果你想在dplyr 中使用这个,那么

    library(dplyr)
    myd %>%
      group_by(id) %>%
      filter(func(status))
    

    【讨论】:

    • 这行得通,谢谢!我发现编写一个 for 循环是编码中最难的部分,但我想也许对于这个问题,没有办法解决它。
    • 是的,有时通常首选的矢量化计算方法等有一个缺点:无内存计算:一个计算与先前计算的结果无关。 for 循环还不错,有时它们确实是最好的方法。
    【解决方案2】:

    我的做法:

    library(dplyr)
    
    myd %>%
      group_by(id) %>% 
      arrange(time) %>%
      filter(status != lag(status) | is.na(lag(status))) %>%
      ungroup() %>%
      arrange(id)
    

    返回:

    # A tibble: 12 x 3
          id  time status
       <dbl> <dbl> <chr>
     1     2     3 mar
     2     2     7 div
     3     2     8 c
     4     2     9 mar
     5     3     2 mar
     6     3     8 div
     7     3    10 mar
     8     3    14 c
     9     3    18 div
    10     4     4 mar
    11     4     7 c
    12     4     9 mar
    

    【讨论】:

    • 我理解删除连续重复的重复,但在 ID 4 的情况下,此人已婚,有孩子,并再次记录为已婚(中间没有离婚),所以婚姻'c' 之后的婚姻仍然与 'c' 之前的婚姻相同,所以应该删除。我将编辑问题以澄清这一点。
    【解决方案3】:

    我会通过在分组数据中创建lag_status 变量来删除状态不变的行:

    > myd %>% 
    +     arrange(id, time) %>% 
    +     group_by(id) %>% 
    +     mutate(lag_status = lag(status)) %>%
    +     ungroup() %>% 
    +     filter(is.na(lag_status) | status != lag_status) %>% 
    +     select(-lag_status)
    # A tibble: 12 x 3
          id  time status
       <dbl> <dbl> <fct> 
     1     2     3 mar   
     2     2     7 div   
     3     2     8 c     
     4     2     9 mar   
     5     3     2 mar   
     6     3     8 div   
     7     3    10 mar   
     8     3    14 c     
     9     3    18 div   
    10     4     4 mar   
    11     4     7 c     
    12     4     9 mar
    

    【讨论】:

    • 如果 'mar' 的序列是连续的,则此方法有效,但在中间有 'c' 时无效(在 id 编号 4 的情况下)。抱歉,我的问题不清楚。
    【解决方案4】:

    我在您的帖子中阅读了两个不同的问题。

    1. 此人第一次结婚时
    2. 如何制作去除冗余状态信息的列表

    看起来你有#1的解决方案,但你实际上想要#2。

    我阅读 #2 是为了过滤掉 id 和 status 与前一行相同的行。看起来像:

    myd %>%
      filter(!(id == lag(id) & status == lag(status))
    

    【讨论】:

    • 对不起,我的问题不清楚(现在已编辑),当 'div' 之间没有发生时,任何 'mar' 行都是多余的,所以当有像 'mar','c 这样的序列时','mar', 'c' (已婚,孩子,已婚,孩子),因为没有检测到 'div',它们被假定为相同的 'mar',所以在这种情况下,第二个 'mar' 是多余的,因为好吧。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-29
    • 1970-01-01
    • 1970-01-01
    • 2018-12-15
    • 2013-07-05
    • 2021-01-31
    相关资源
    最近更新 更多