0

ユーザー定義関数で行列の各要素を計算しようとしています。二重forループ、ネストされたsapply、およびapplyafterを使用しましたexpand.grid

# create dataset
ll = lapply(1:20, FUN = function(x) floor(runif(n=floor(runif(1,10,30)),1,50)))

# sapply line
doSapply = function(ll){
  m = sapply(1:length(ll),FUN = function(x){sapply(1:length(ll),FUN = function(y){if(length(intersect(ll[[x]],ll[[y]]))>1){return(1)}else{return(0)}})})

}


doFor = function(ll){
  m = matrix(rep(0,length(ll)*length(ll)),length(ll))
  # double for loop
  for(x in 1:length(ll)){
    for(y in 1:length(ll)){
      if(length(intersect(ll[[x]],ll[[y]]))>1){
        m[x,y] = 1
      } else{
        m[x,y] = 0
      } 
    }
  }
}

doApply = function(ll){
  x = expand.grid(1:length(ll),1:length(ll))
  vals = apply(x,1,FUN = function(x){
    if(length(intersect(ll[[x[1]]],ll[[x[2]]]))>1){
      return(1)
    } else{
      return(0)
    }
  } )
  matrix(vals,nrow=length(ll),byrow=FALSE)
#   return(matrix(vals,nrow=length(ll),byrow=FALSE))
}
timeSapply = system.time(doSapply(ll))
timeFor = system.time(doFor(ll))
timeApply = system.time(doApply(ll))

私はより洗練されたソリューションを探しています (もちろん、より高速です)。私はアウターを使おうとしています、そして私は書きました:

doOuter = function(ll){
  outer(1:length(ll),1:length(ll),FUN = function(x,y){if(length(intersect(ll[[x]],ll[[y]]))>1){return(1)}else{return(0)}})
}

私は得たError in ll[[y]] : recursive indexing failed at level 2

Outer は関数をベクトル化する必要があると考えたので、試してみました。

doMatch = function(x,y,ll){
  if(length(intersect(ll[[x]],ll[[y]]))>1){return(1)}else{return(0)}
}

doMatVec = Vectorize(doMatch)
outer(1:length(ll),1:length(ll),doMatVec,ll )

そして私は得たError in ll[[x]] : subscript out of bounds

私がやろうとしていることの一般的な考え方について、Vectorizeで間違っているかもしれないと思いますが、ここで助けていただければ幸いです。plyr/ -も見ていますが、dplyrあまり成功していません。

4

0 に答える 0