如何在 R 中找到互补的连续整数区间?

问题描述 投票:0回答:2

我有一组在某个范围内的整数间隔,例如1-20,我想为它们生成互补的连续间隔,如下所示:

intervals <- list(3:6, 10:11, 19:20)

complementary_intervals <- list(1:2, 7:9, 12:18)

或者,我将有一个包含开始和结束整数的数据框/小标题:

library(tidyverse)

intervals <- tribble(
 ~start, ~end,
 3, 6,
 10, 11,
 19, 20
)

如何找到互补区间?我尝试使用

set_diff
生成不包含在间隔中的整数,但后来我陷入了从中寻找连续间隔的困境。

r tidyverse intervals
2个回答
2
投票

在 @Frieke 的基本 R 解决方案之上,我想使用最近的

tidyverse
包提出一种
ivs
方法,该方法可以方便地处理间隔:

library(ivs)
intervals <- tribble(
  ~start, ~end,
  3, 6,
  10, 11,
  19, 20
)

#Create the intervals (iv) object
iv1 = iv(intervals$start, intervals$end)
iv2 = iv(1, 20)

#Compute the difference
iv_difference(iv2, iv1)
# <iv<double>[3]>
# [1] [1, 3)   [6, 10)  [11, 19)

#You can easily transform this object back to a `normal` data.frame/tibble:
iv_diff <- iv_difference(iv2, iv1)
tibble(start = iv_start(iv_diff),
       end = iv_end(iv_diff))

# # A tibble: 3 × 2
#   start   end
#   <dbl> <dbl>
# 1     1     3
# 2     6    10
# 3    11    19

1
投票

按照@Maël 在评论中的建议,我发布我的评论作为答案。

尝试

intervals <- list(3:6, 10:11, 19:20)
complementary_intervals <- list(1:2, 7:9, 12:18, 21:120)

x <- setdiff(1L:120L, unlist(intervals)) 
( y <- split(x, cumsum(c(1L, diff(x) != 1L))) )

这给出了

#> $`1`
#> [1] 1 2
#> 
#> $`2`
#> [1] 7 8 9
#> 
#> $`3`
#> [1] 12 13 14 15 16 17 18
#> 
#> $`4`
#>   [1]  21  22  23  24  25  26  27  28  29  30  31  32  33  34  35  36  37  38
#>  [19]  39  40  41  42  43  44  45  46  47  48  49  50  51  52  53  54  55  56
#>  [37]  57  58  59  60  61  62  63  64  65  66  67  68  69  70  71  72  73  74
#>  [55]  75  76  77  78  79  80  81  82  83  84  85  86  87  88  89  90  91  92
#>  [73]  93  94  95  96  97  98  99 100 101 102 103 104 105 106 107 108 109 110
#>  [91] 111 112 113 114 115 116 117 118 119 120

当然,这两行可以很容易地重写为管道版本。这将使环境保持清洁——好主意。要将结果与

base R
进行比较,您可以使用
mapply()
,如下所示

mapply(FUN = "%in%", complementary_intervals, y)

创建于 2023-10-11,使用 reprex v2.0.2

© www.soinside.com 2019 - 2024. All rights reserved.