如何从R中的数字列表创建多个范围?

时间:2014-03-06 03:25:15

标签: r range

如果我有一个数字列表:

> list1
 [1]   58659   59837 2603675 2607619 2607631 2608098 2608106 2608975 2608978 2609613
 [11] 2609635 2610225 2610235 2610408 2610453 2610782 2610799 2611212 2611232 2611642
 [21] 2611646 2611825 2611828 2612151 2612154 2612741 2612943 2614220 2614222 2614941
 [31] 2615008 2616276 2616304 2617656

是否存在根据阈值创建两个列表的函数(例如100000)我提供并导致

[1] 58659 59837 2603675 2617656

另一个更简单的例子

>list2
[1] 1 2 3 4 11 12 13 14

阈值为2,它会发出

[1] 1 4 11 14

2 个答案:

答案 0 :(得分:1)

您可以使用以下技巧找到这些范围(其中list2是您的向量,2是您的阈值):

tapply(list2, cumsum(c(TRUE, diff(list2) > 2)), range)

它可能看起来很神秘,但这是一个演练。您可以从有用的diff函数开始查找连续的差异:

list2 = c(1, 2, 3, 4, 11, 12, 13, 14)
diff(list2)
# 1 1 1 7 1 1 1

然后,如果你检查哪些项目大于你的阈值,你会发现休息(新组的开始)的位置是:

diff(list2) > 2
# [1] FALSE FALSE FALSE  TRUE FALSE FALSE FALSE

请注意,它比原始列表短一个(因为连续差异的数量是n - 1)。要解决这个问题,请在开头添加一个TRUE(因为第一个元素始终是新组的开头):

c(TRUE, diff(list2) > 2)
# [1] TRUE FALSE FALSE FALSE  TRUE FALSE FALSE FALSE

但这只是告诉你休息的位置,而不是每个元素的组。但累积总和将告诉你(因为总和将TRUE视为1而FALSE视为0):

cumsum(c(TRUE, diff(list2) > 2))
# [1] 1 1 1 1 2 2 2 2

现在我们到了某个地方! tapply是一个有用的函数,它根据另一个向量定义的组对向量应用函数,就像我们这里的这些1和2组一样。我们想要应用range函数来学习每个组中的范围(最小和最大):

result = tapply(list2, cumsum(c(TRUE, diff(list2) > 2)), range)
result[[1]]
# 1 4
result[[2]]
# 11 14

请注意,这是一个列表,在我看来,它比像1 4 11 14这样的连接向量更有用。但是,如果你确实想要这种格式,你可以这样做:

do.call(c, result)

将它们组合成一个矢量。

答案 1 :(得分:0)

我认为您希望使用diff找出每个连续值之间的空格,然后将值提取到该空间的左侧和右侧。这是一个示例函数:

f<-function(x,thresh){
  pos<-which(diff(x)>thresh)
  x[unique(c(1,pos,pos+1,length(x)))]
}

x<-unname(unlist(read.table(textConnection('58659   59837 2603675 2607619 2607631 2608098 2608106 2608975 2608978 2609613 2609635 2610225 2610235 2610408 2610453 2610782 2610799 2611212 2611232 2611642 2611646 2611825 2611828 2612151 2612154 2612741 2612943 2614220 2614222 2614941 2615008 2616276 2616304 2617656'))))
f(x,10000)
# [1]   58659   59837 2603675 2617656
x<-c(1:4,11:14)
f(x,2)
# [1]  1  4 11 14