首页 > 解决方案 > 为组中的连续出现创建索引

问题描述

我在 R 中有一个大型数据框,两组可能如下所示:

id     tnr
1      1
1      1-3
1      4
1      5
1      6
1      6-8
1      8-9
1      10
1      10-11
1      12
2      1
2      2
2      3
2      3-4

问题是重叠的数字。第一步,我在-字符处拆分数字,以便将两个部分都转换为数字。ifelse然后,我与-statements 进行了一些比较,以确定重叠的数字,这给了我这样的数据框:

id     tnr     ovlp
1      1       1
1      1-3     1
1      4       0
1      5       0
1      6       1
1      6-8     1
1      8-9     1
1      10      1
1      10-11   1
1      12      0
2      1       0
2      2       0
2      3       0
2      3-4     1

在最后一步中,我需要确定组内每个子组的出现。结果应该是这样的:

id     tnr     ovlp     occ
1      1       1        1
1      1-3     1        1
1      4       0        0
1      5       0        0
1      6       1        2
1      6-8     1        2
1      8-9     1        2
1      10      1        3
1      10-11   1        3
1      12      0        0
2      1       0        0
2      2       0        0
2      3       1        1
2      3-4     1        1

我首先考虑使用0作为分隔符对每个序列进行编号。这适用于大多数情况,但有时,0两个序列之间没有。就像在示例中一样,当我在第一组中有 6-9 和 10-11 的重叠数字时。所以,我想我需要以ifelse某种方式使用我的 - 语句将此索引粘贴到 -occ列,但我不知道如何。有任何想法吗?任何帮助表示赞赏。

谢谢!

编辑:我用来识别重叠数字的代码:

df <- df %>% 
  mutate(ovlp = ifelse(tnr_a == lag(tnr_a) & id == lag(id) |
                               is.na(tnr_b) == FALSE & tnr_b == lag(tnr_b) & id == lag(id) |
                               tnr_a == lag(tnr_b & is.na(tnr_b) == FALSE & is.na(lag(tnr_b)) == FALSE & id == lag(id) |
                               lag(tnr_a) == tnr_b & is.na(tnr_b) == FALSE & is.na(lag(tnr_b)) == FALSE & id == lag(id) |
                               tnr_b == lag(tnr_b) & is.na(tnr_b) == FALSE & is.na(lag(tnr_b)) == FALSE & id == lag(id) |
                               str_detect(tnr, "\\-") == TRUE & lag(tnr_a) > tnr_a & lag(tnr_a) < tnr_b |
                               lag(str_detect(tnr, "\\-")) == TRUE & lag(tnr_a_) < tnr_a & lag(tnr_a) > tnr_b, 
                             1, 0)) %>%
  relocate(ovlp, .after = tnr) %>% 
  mutate(ovlp = ifelse(lead(ovlp) == 1 & lead(id) == id, 1, tnr_gruppe))

编辑 2:样本数据

df <- structure(list(id = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
2L, 2L, 2L, 2L), tnr = c("1", "1-3", "4", "5", "6", "6-8", "8-9", 
"10", "10-11", "12", "1", "2", "3", "3-4")), class = "data.frame", row.names = c(NA, 
-14L))

标签: rdplyr

解决方案


一个选项涉及dplyr并且tidyr可能是:

df %>%
 rowid_to_column() %>%
 separate_rows(tnr) %>%
 group_by(id, tnr) %>%
 mutate(ovlp = as.integer(n() > 1)) %>%
 group_by(id) %>%
 mutate(occ = with(rle(ovlp), rep(cumsum(values) * values, lengths))) %>%
 group_by(rowid) %>%
 summarise(across(-tnr, first),
           across(tnr, ~ paste(., collapse = "-"))) 

   rowid    id  ovlp   occ tnr  
   <int> <int> <int> <int> <chr>
 1     1     1     1     1 1    
 2     2     1     1     1 1-3  
 3     3     1     0     0 4    
 4     4     1     0     0 5    
 5     5     1     1     2 6    
 6     6     1     1     2 6-8  
 7     7     1     1     2 8-9  
 8     8     1     1     3 10   
 9     9     1     1     3 10-11
10    10     1     0     0 12   
11    11     2     0     0 1    
12    12     2     0     0 2    
13    13     2     1     1 3    
14    14     2     1     1 3-4 

推荐阅读