2

我有一个数据集,其中包括物种列表、它们的数量以及调查开始时的天数。由于没有采样很多天,因此一天不是连续的。因此,例如,可能在第 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          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)
 } 

我需要帮助的两个问题:

  1. 虽然我的函数确实返回了所需的点数,但它并不以我的搜索值为中心。这是有道理的,因为随着我变得更宽,我得到更多的点,当我对它们进行排序并选择第一个 n 时,它们往往不是低值。

  2. 其次,我如何得到实际的行?现在我有另一个函数可以使用which, 然后将rbind这些行放在一起来定位这些行。似乎应该有更好的方法。

谢谢!

4

2 回答 2

3

喜欢 Charles 的解决方案,它非常适合 n=2 的情况。唉,它不能扩展到更大的窗户。它仍然存在 OP 描述的问题:对于较大的窗口,选择不会以搜索值为中心。鉴于 n 是偶数,我提出了以下解决方案,主要基于查尔斯的想法。

该函数控制边界。如果有 100 天,并且下一个中点是倒数第二天,则窗口 4 意味着您选择索引 101,它给出NA. 此函数移动窗口,使所有选定的索引都位于原始数据内。这还有一个副作用,即根据 start( st)、length( l) 和 window( n) 的值,开始和结束的值有更高的机会被选中两次。长度应始终至少是窗口大小的两倍。

该函数的输出是引导样本的索引。它可以用作posCharles 在向量和数据帧上的变量。

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)
}

然后

>   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
> 

编辑:关于时间序列的引导,您应该通过 The CRAN taskview on time series,尤其是关于重采样的部分。对于不规则的时间序列,该zoo软件包还提供了一些可以派上用场的其他功能。

于 2010-10-17T00:17:59.800 回答
1

像下面这样的东西怎么样:

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/lapply/seq 组合稍微干净一些:

pos = match(x[outer(c(0, 1), findInterval(search, x), `+`)], day)

另请注意,如果您想要一个更大的窗口(例如 4),只需返回一点:

pos = match(x[outer(-1:2, findInterval(search, x), `+`)], day)
于 2010-10-16T22:03:23.980 回答