R 从数字字符串中检测范围

R 从数字字符串中检测范围,r,vector,range,R,Vector,Range,我有一个向量,看起来像这样 c(3,4,5,6,7,10,11,14,17,18,19,54,55,56,59,61)->k 如何轻松检测连续数字的范围,以便 3:7,10,11,14,17:19,54:56,59,61 并将其保存在一个新的向量中?在有一个范围(:)的情况下,最好保存该范围的中位数,这样输出会更精确 5,10,11,14,18,55,59,61 有没有其他快速解决方案,也可以处理不象这样升序的向量 12,3,4,5,0,7 进入 12,4,0,71)试试这个: t

我有一个向量,看起来像这样

c(3,4,5,6,7,10,11,14,17,18,19,54,55,56,59,61)->k
如何轻松检测连续数字的范围,以便

3:7,10,11,14,17:19,54:56,59,61 
并将其保存在一个新的向量中?在有一个范围(:)的情况下,最好保存该范围的中位数,这样输出会更精确

5,10,11,14,18,55,59,61
有没有其他快速解决方案,也可以处理不象这样升序的向量 12,3,4,5,0,7

进入 12,4,0,7

1)试试这个:

tapply(k, cumsum(c(TRUE, diff(k) != 1)), median)
给予:

   1    2    3    4    5    6    7 
 5.0 10.5 14.0 18.0 55.0 59.0 61.0 
      1       2       3       4       5       6       7 
  "3:7" "10:11"    "14" "17:19" "54:56"    "59"    "61" 
$`1`
[1] 3 4 5 6 7

$`2`
[1] 10 11

$`3`
[1] 14

$`4`
[1] 17 18 19

$`5`
[1] 54 55 56

$`6`
[1] 59

$`7`
[1] 61
2)也可以尝试以下方法:

f <- function(x) if (length(x) == 1) x else paste(x[1], x[length(x)], sep = ":")
tapply(k, cumsum(c(TRUE, diff(k) != 1)), f)
3)这是:

tapply(k, cumsum(c(TRUE, diff(k) != 1)), toString)
split(k, cumsum(c(TRUE, diff(k) != 1)))
鉴于此:

              1               2               3               4               5 
"3, 4, 5, 6, 7"        "10, 11"            "14"    "17, 18, 19"    "54, 55, 56" 
              6               7 
           "59"            "61" 
4)这是:

tapply(k, cumsum(c(TRUE, diff(k) != 1)), toString)
split(k, cumsum(c(TRUE, diff(k) != 1)))
给予:

   1    2    3    4    5    6    7 
 5.0 10.5 14.0 18.0 55.0 59.0 61.0 
      1       2       3       4       5       6       7 
  "3:7" "10:11"    "14" "17:19" "54:56"    "59"    "61" 
$`1`
[1] 3 4 5 6 7

$`2`
[1] 10 11

$`3`
[1] 14

$`4`
[1] 17 18 19

$`5`
[1] 54 55 56

$`6`
[1] 59

$`7`
[1] 61

上述各项都不需要任何外部软件包。

使用
vapply
range
的选项(仅
基本R
功能)

对于大向量,正如@David Arenburg在评论中提到的,一些
data.table
选项是

 library(data.table)
 as.data.table(k)[, median(k), cumsum(c(TRUE, diff(k) != 1))]
 as.data.table(k)[, paste(unique(range(k)), collapse = ";"), 
               cumsum(c(TRUE, diff(k) != 1))
更新 使用新向量“k1”


k1是否有机会修改它在十进制数不是正常数(10.5..在上述情况下)的情况下自动取整?尝试
round(tapply(…)
我的向量非常长,超过了1 mill的值,并且不是直线上升的。碰巧它可以是12,3,4,5,07…有好的解决方案吗?哪些可以快速处理?如果是这样,请解决这个问题。不是完全重复,但非常相关:您为什么使用
->
?这是某种叛变吗?:)那里有一些很好的解决方案(粘贴(唯一(范围(x))
非常出色。不确定是否值得添加
as.data.table(k)[,中位数(k),求和(c(TRUE,diff(k)!=1)];as.data.table(k)[,粘贴(唯一(范围(k)),collapse=“;”),求和(c(TRUE,diff(k)!=1))]
作为大向量的可能增强。或
if&else
版本
as.data.table(k)[,if(.N>1L)粘贴(范围(k),collapse=“;”))else粘贴(k),cumsum(c(真,差(k)!=1))]
@davidernburg尝试了数据表解决方案,结果发现它不起作用,因为数字不是递增的..所以看看输入向量,如12,3,4,5,0,7@triub感谢您的评论。您是否尝试过
vapply
?@akrun是的,但至少对于100k值的测试数据来说,它比数据表慢得多……它是否使用了it inocorrect?@triub根据显示的示例,它正在为data.table工作。我用结果更新了帖子