データが連続していない場合、y値yに最も近いランダムでn値をサンプリングするにはどうすればよいですか?

StackOverflow https://stackoverflow.com/questions/3950877

質問

私は、調査が始まったときからの種、それらの数、および日数のリストを含むデータセットを持っています。多くの日がサンプリングされていないため、日は継続的ではありません。たとえば、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日目ではありません)。この場合、1日が34と39である2つの行をつかみます。

次に、30〜35を追加し、65周辺で2つのポイントを探します。すすぎ、データセットの最後に到達するまで繰り返します。

サンプリングを行うためにこの関数を書きましたが、欠陥があります(以下を参照):

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

私が助けが必要な2つの問題:

  1. 私の関数は望ましいポイント数を返しますが、検索値を中心としていません。私がより広くなると、より多くのポイントが得られ、それらを並べ替えて最初のnを選ぶとき、それらは低い値ではない傾向があるため、理にかなっています。

  2. 第二に、実際の行を出すにはどうすればよいですか?今のところ、私はこれらの行を使用してこれらの行を見つける別の関数を持っています which, 、 それから rbind 'それらの行を一緒にします。より良い方法があるべきだと思われます。

ありがとう!

役に立ちましたか?

解決

次のようなものはどうですか:

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

これはおそらく、非公開/Lapply/seqコンボよりもわずかにきれいです:

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

また、より大きなウィンドウ(たとえば4)が必要な場合は、少し戻るだけの問題であることに注意してください。

pos = match(x[outer(-1:2, findInterval(search, x), `+`)], day)

他のヒント

チャールズの解決策が大好きでした。チャールズは、ケースn = 2で完全に機能します。残念ながら、大きな窓には拡張できません。 OPで説明されている問題がまだあります。より大きなウィンドウを使用すると、選択は検索値を中心としていません。 nが偶数であることを考えると、私はチャールズのアイデアに大きく基づいて、次の解決策を思いつきました。

関数は境界を制御します。 100日があり、次のミッドポイントが最後の2日目であると言う場合、4のウィンドウはインデックス101を選択することを意味します。 NA. 。この関数はウィンドウをシフトするため、選択したすべてのインデックスが元のデータ内にあります。これには、開始値に応じて副作用があります(st)、 長さ(l)とウィンドウ(n)開始と終わりの値は、2回選択される可能性が高くなります。長さは、常にウィンドウサイズの少なくとも2倍である必要があります。

関数の出力は、ブートストラップサンプルのインデックスです。として使用できます 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)
}

それで

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

編集:時系列のブートストラップについては、 時系列のクランタスクビュー, 、特に再サンプリングに関するセクション。不規則な時系列の場合、 zoo パッケージは、便利になる可能性のある他の機能も提供しています。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top