我有一组在某个范围内的整数间隔,例如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
生成不包含在间隔中的整数,但后来我陷入了从中寻找连续间隔的困境。
在 @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
按照@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