【问题标题】:Create index for sequential occurences in group为组中的连续出现创建索引
【发布时间】:2021-01-04 11:17:50
【问题描述】:

我在 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-statements 将此索引粘贴到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))

【问题讨论】:

  • 为什么第一个id 3中10和10-11是occ?
  • 您能否将您的数据集(使用 dput() )和您当前的代码也放入您的问题中?这将使提供帮助变得容易得多。乍一看,我会说一种方法可能是将您的 tnr 列分成两列(每行的最小值和最大值)。如果一行的最大值小于下一行的最小值,则您有一个新组。
  • @tmfmnk:因为它是新的子组。 occ = 2 表示 6 到 9 的重叠数,occ = 3 表示 10 到 11 的重叠数。
  • @MarioNiepel:很遗憾,我无法共享数据集,因为它来自机密来源。不过,我包含了用于识别重叠数字的代码。 tnr_atnr_b 指的是tnr 的数字部分。当没有第二个数字部分时,tnr_bNA。我之前做了几步拆分。但是,我仍然无法弄清楚如何在我的组中对这些序列进行编号...
  • 我不建议分享比您已经展示的更多的数据。您希望人们能够帮助您,而无需他们手动输入您的数据。如果您通过 dput() 共享它,则可以将其复制并粘贴到测试代码中。

标签: r dplyr


【解决方案1】:

涉及dplyrtidyr 的选项可能是:

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 

【讨论】:

  • 谢谢,这对我的示例数据很有帮助。我尝试将其应用于我的数据集,但遇到了一些问题。查找重叠的标准有点复杂,分隔符并不总是“-”。但是你的代码给了我一些朝着正确方向发展的例子。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-10-15
  • 1970-01-01
  • 2019-11-23
  • 2011-09-08
  • 1970-01-01
  • 1970-01-01
  • 2020-01-02
相关资源
最近更新 更多