R 当数据不连续时,如何随机抽取距离值y最近的n个值?
我有一个数据集,包括物种列表、它们的数量以及调查开始时的天数。由于许多天没有取样,所以这一天不是连续的。例如,在第5天、第6天、第9天、第10天、第15天、第34天、第39天等等,可能会有鸟类被计数。我将最早的日期设置为第0天 示例数据:R 当数据不连续时,如何随机抽取距离值y最近的n个值?,r,time-series,statistics-bootstrap,R,Time Series,Statistics Bootstrap,我有一个数据集,包括物种列表、它们的数量以及调查开始时的天数。由于许多天没有取样,所以这一天不是连续的。例如,在第5天、第6天、第9天、第10天、第15天、第34天、第39天等等,可能会有鸟类被计数。我将最早的日期设置为第0天 示例数据: species counts day Blue tit 234 0 Blue tit 24 5 Blue tit 45 6 Blue tit 32
species counts day
Blue tit 234 0
Blue tit 24 5
Blue tit 45 6
Blue tit 32 9
Blue tit 6 10
Blue tit 98 15
Blue tit 40 34
Blue tit 57 39
Blue tit 81 43
..................
我需要引导这些数据,并得到一个结果数据集,在其中我指定何时开始,以什么间隔进行,以及采样点数
示例:假设我随机选择第5天作为开始日,间隔为30,采样行数为2。
这意味着我将从5开始,再加上30,然后在35天左右寻找2行,而不是35天本身。在本例中,我将抓住第34天和第39天的两行
下一步我加30到35,然后寻找65左右的两点。冲洗,重复,直到数据集结束
我编写此函数是为了进行采样,但它存在缺陷,请参见以下内容:
resample <- function(x, ...) x[sample.int(length(x), ...)]
locate_points<- function(dataz,l,n) #l is the interval, n is # points to sample. This is called by another function that specifies start time among other info.
{
tlength=0
i=1
while(tlength<n)
{
low=l-i
high=l+i
if(low<=min(dataz$day)) { low=min(dataz$day) }
if(high>=max(dataz$day)) { high=max(dataz$day) }
test=resample(dataz$day[dataz$day>low & dataz$day<high & dataz$day!=l])
tlength=length(test)
i=i+1
}
test=sort(test)
k=test[1:n]
return (k)
}
我需要帮助解决两个问题:
虽然我的函数返回所需的点数,但它并不是以我的搜索值为中心的。这是有意义的,因为当我变得更宽时,我会得到更多的点,当我对它们进行排序并选择第一个n时,它们往往不是低值
第二,如何得到实际的行?现在我有另一个函数来定位这些行,使用它,然后将这些行绑定在一起。看来应该有更好的办法
谢谢 下面的例子怎么样:
day = 1:1000
search = seq(from=5, to=max(day), by=30)
x = sort(setdiff(day, search))
pos = match(x[unlist(lapply(findInterval(search, x), seq, len=2))], day)
day[pos]
要从data.frame中获取行,只需将其子集:
rows = data[pos, ]
这可能比unlist/lappy/seq组合稍微干净一些:
pos = match(x[outer(c(0, 1), findInterval(search, x), `+`)], day)
还要注意的是,如果你想要一个更大的窗口,比如说4,只需往回走一点:
pos = match(x[outer(-1:2, findInterval(search, x), `+`)], day)
我喜欢Charles的解决方案,它对n=2的情况非常有效。唉,它不能扩展到更大的窗口。它仍然存在OP描述的问题:对于较大的窗口,选择不以搜索值为中心。考虑到n是偶数,我提出了以下解决方案,主要基于Charles的想法 该函数控制边界。如果有100天,下一个中点是最后一天的第二天,那么窗口为4意味着您选择索引101,这将给出NA。此函数移动窗口,使所有选定索引位于原始数据内。这还有一个副作用,即根据开始和结束的开始st、长度THL和窗口N值的值,选择两次的几率更高。长度应始终至少为窗口大小的两倍 函数的输出是引导样本的索引。它可以用作向量和数据帧上Charles的pos变量
bboot <- function(day,st,l,n){
mid <- seq(st,max(day),by=l)
x <-sort(setdiff(day,mid))
lx <- length(x)
id <- sapply(mid,
function(y){
m <- match(T,x>y)
seq(
from=min( lx-n, max(1,m+(-n/2)) ),
to=min( lx, max(n,m+(n/2-1)) )
)
}
)
pos <- match(x[id],day)
return(pos)
}
然后
编辑:关于时间序列的引导,您应该阅读,特别是关于重采样的部分。对于不规则的时间序列,zoo软件包还提供了许多其他方便的功能。非常感谢,Charles!我从你的例子中学到了很多。干杯。谢谢,很高兴它有帮助。事实上,这似乎比我预期的要复杂——可能有一种更简单的方法……哦,有一件事我没有提到,这只是针对一个物种。你可以把你的数据按物种分类,或者用tapply按物种分类。不过我忘了一件事。每个样本的最低值应成为下一轮的起始值。这就给搜索序列带来了麻烦。但我应该能够解决这个问题。我不知道我是否正确理解你,但你的功能似乎并没有真正做到你所描述的。您具体在哪里指定每次添加的时间间隔?如果您添加一些注释来解释l、n等实际上是什么,这将非常有用。@Joris此函数有另一个指定开始时间的包装器。我对上面的代码做了一些评论。这似乎是一种奇怪的方法来引导数据的选择。你的潜在动机是什么?@hadley:不太可能,但我们的目标是看看我们是否能够仅使用存在/不存在数据预测人口趋势。这个问题与模拟在这种情况下缩短采样间隔将如何影响我们检测趋势的能力有关。您是否完全依赖于此采样方案?为什么不在整个数据范围内均匀分布,然后选择最接近这些数据的日期呢?很高兴听到您正在使用ggplot2!
> day <- sample(1:100,50)
> sample.rownr <- bboot(day,10,20,6)
> sort(day)
[1] 3 4 5 7 9 10 13 15 16 18 19 21 22 24 25 26 27 28 29
[20] 30 31 32 35 36 38 40 45 49 51 52 54 55 58 59 62 65 69 72 73
[40] 74 80 84 87 88 91 92 94 97 98 99
> day[sample.rownr]
[1] 5 7 9 13 15 16 27 28 29 31 32 35 40 45 49 51 52 54 62
[20] 65 69 72 73 74 84 87 88 91 92 94
>