1

3 つのデータ ソースがあります。

types<-c(1,3,3)
places<-list(c(1,2,3),1,c(2,3))
lookup.counts<-as.data.frame(matrix(runif(9,min=0,max=10),nrow=3,ncol=3))
assigned.places<-rep.int(0,length(types))

「タイプ」ベクトルの数字は、特定の観測がどの「タイプ」であるかを教えてくれます。場所リストのベクトルは、観測がどの場所で見つかるかを教えてくれます (一部の観測は 1 か所だけで見つかり、その他はすべての場所で見つかります)。定義により、タイプには 1 つのエントリがあり、観測ごとに場所に 1 つのリストがあります。Lookup.counts は、(別のデータ ソースから生成された) 各場所にある各タイプの観測の数を教えてくれます。

lookup.counts から生成された確率に基づいて、各観測をランダムに場所に割り当てたいと考えています。for ループを使用すると、次のようになります」

for (i in 1:length(types)){
  row<-types[i]
  columns<-places[[i]]
  this.obs<-lookup.counts[row,columns] #the counts of this type in each place
  total<-sum(this.obs)
  this.obs<-this.obs/total #the share of observations of this type in these places
  pick<-runif(1,min=0,max=1)

  #the following should really be a 'while' loop, but regardless it needs help
  for(j in 1:length(this.obs[])){
    if(this.obs[j] > pick){
      #pick is less than this county so assign
      pick<- 100 #just a way of making sure an observation doesn't get assigned twice
      assigned.places[i]<-colnames(lookup.counts)[j]
    }else{
      #pick is greater, move to the next category
      pick<- pick-this.obs[j]
    }
  }
}

これをどうにかしてベクトル化しようとしましたが、'places' と 'this.obs' の可変長に引っかかっています。

もちろん、実際には、lookup.counts テーブルはかなり大きく (500 x 40)、長さ 1 から長さ 39 の場所リストを含む 900K の観測があります。

4

2 に答える 2

2

内側のループをベクトル化するには、sampleorを使用sample.intして、所定の確率を持ついくつかの選択肢から選択できます。私があなたのコードを間違って読んでいない限り、次のようなものが必要です:

assigned.places[i] <- sample(colnames(this.obs), 1, prob = this.obs)

colnames(lookup.counts)代わりに使っていることに少し驚いています。これもサブセット化すべきではありませんcolumnsか?何かを見逃したか、コードにバグがあるようです。

リストの長さが異なることは、外側のループをベクトル化する上で深刻な障害となります。おそらく、Matrixパッケージを使用して、その情報をスパース行列として保存できます。次に、確率にそのベクトルを掛けるだけで、特定の観測の場所リストにない列を除外できます。しかし、おそらくapply上記のサンプリング コードを引き続き使用するため、リストを保持し、何らかの形式を使用applyしてそれを反復処理することもできます。

全体的な結果は次のようになります。

assigned.places <- colnames(lookup.counts)[
  apply(cbind(types, places), 1, function(x) {
    sample(x[[2]], 1, prob=lookup.counts[x[[1]],x[[2]]])
  })
]

cbindandの使用はapply特に美しいわけではありませんが、機能しているようです。それぞれは、タイプと対応する場所xの 2 つの項目のリストです。これらを使用して、あなたと同じようにインデックスを作成します。次に、添え字で使用した列の 1 つのインデックスを選択するときに、見つかったカウントを相対確率として使用します。これらすべての数値が によって単一のベクトルに組み立てられた後でのみ、インデックスは に基づく名前に変わります。x[[1]]x[[2]]lookup.countsapplycolnames

cbind一緒に詰め込むのではなく、代わりにインデックスのみを反復すると、物事が高速かどうかを確認できます。

assigned.places <- colnames(lookup.counts)[
  sapply(1:length(types), function(i) {
    sample(places[[i]], 1, prob=lookup.counts[types[i],places[[i]]])
  })
]
于 2012-10-22T16:09:35.073 に答える
1

これもうまくいくようです:

# More convenient if lookup.counts is a matrix.
lookup.counts<-matrix(runif(9,min=0,max=10),nrow=3,ncol=3)
colnames(lookup.counts)<-paste0('V',1:ncol(lookup.counts))

# A function that does what the for loop does for each i
test<-function(i) {
  this.places<-colnames(lookup.counts)[places[[i]]]
  this.obs<-lookup.counts[types[i],this.places]
  sample(this.places,size=1,prob=this.obs)
}

# Applies the function for all i
sapply(1:length(types),test)
于 2012-10-22T16:27:15.757 に答える