1

私はRを使うのが初めてです。そのため、applyの使い方がわかりません。applyを使用して関数を高速化したいと思います。

for(i in 1: ncol(exp)){
 for (j in 1: length(fe)){
  tmp =TRUE
  id = strsplit(colnames(exp)[i],"\\.")
  if(id == fe[j]){
   tmp = FALSE
  }
  if(tmp ==TRUE){
   only = cbind(only,c(names(exp)[i],exp[,i]) )
  }
 }
}

上記のようにapply関数を使用するにはどうすればよいですか?

編集 :

非常に良い説明をありがとうございました、そして私の悪い説明をお詫び申し上げます。あなたはすべてが正しいと思いますが、feで一致を削除したい場合。

Exp <- data.frame(A.x=1:10,B.y=10:1,C.z=11:20,A.z=20:11)

fe<-LETTERS[1:2]

その場合、結果は「C」の列名のみになります。それ以外はすべて削除する必要があります。

1   C.z 
2    11 
3    12   
4    13   
5    14 
6    15  
7    16  
8    17  
9    18   
10   19  
11   20   
4

2 に答える 2

4

編集:名前がfeに表示される列のみを削除したい場合は、次のようにするだけです。

Exp <- data.frame(A.x=1:10,B.y=10:1,C.z=11:20,A.z=20:11)
fe<-LETTERS[1:2]

id <- sapply(strsplit(names(Exp),"\\."),
    function(i)!i[1] %in% fe)
Exp[id]

このコードは、(更新された)forループとまったく同じように機能しますが、はるかに効率的です。feをループする必要はなく、%in%関数はベクトル化されます。

名前がドットの間のどこにでも表示される場合は、

id <- sapply(strsplit(names(Exp),"\\."),
    function(i)sum(i %in% fe)==0)

あなたのコードはいくつかの非常に面白いことをします、そして私はあなたが何をしようとしているのか正確にはわかりません。1つstrsplitは、リストを提供するため、リスト自体id == fe[j]でない限り、常にfalseを返します。fe[j]そして、私はそれがそうであるとは思えません...だから私はあなたのコードを次のように修正します

id = strsplit(colnames(Exp)[i],"\\.")[[1]][1]

ドットの前にあるすべてのものと比較したい場合、または

id = unlist(strsplit(colnames(Exp)[i],"\\.")) 

文字列内のすべてと比較したい場合。その場合は、%in%代わりにを使用する必要が==あります。

次に、取得するのは文字マトリックスです。これは基本的に行を乗算します。fe [j]のすべての要素が一意である場合は、次のようにすることもできます。

only <- rbind(names(exp),exp)
only <- do.call(cbind,lapply(mat,function(x) 
       matrix(rep(x,ncol(exp)-1),nrow=nrow(exp)+1)
))

コード内のロジックが理にかなっていると仮定すると(サンプルデータを適用しなかったため、これを知ることは不可能です)、最適化が実行されます。

mat <- rbind(names(Exp),Exp)

do.call(cbind,
    lapply(mat, function(x){
        n <- sum(!fe %in% strsplit(x[1],"\\.")[[1]][1])
        matrix(rep(x,n),nrow=nrow(mat))
}))

名前のどこかにfe[j]が表示されているかどうかに関心がある場合は、コードを次のように変更できることに注意してください。

do.call(cbind,
    lapply(mat, function(x){
        n <- sum(!fe %in% unlist(strsplit(x[1],"\\.")))
        matrix(rep(x,n),nrow=nrow(mat))
}))

これがあなたが望むものを返さない場合、あなたのコードもそれをしません。次のサンプルデータで確認したところ、すべて同じ結果が得られました。

Exp <- data.frame(A.x=1:10,B.y=10:1,C.z=11:20,A.z=20:11)
fe <- LETTERS[1:4]
于 2011-03-28T14:11:38.583 に答える
2

関数ファミリーはapply()便利な関数です。それらは、適切に記述された for ループまたはベクトル化された関数よりも必ずしも高速ではありません。例えば:

set.seed(21)
x <- matrix(rnorm(1e6),5e5,2)

system.time({
  yLoop <- x[,1]*0  # preallocate result
  for(i in 1:NROW(yLoop)) yLoop[i] <- mean(x[i,])
})
#    user  system elapsed 
#   13.39    0.00   13.39 
system.time(yApply <- apply(x, 1, mean))
#    user  system elapsed 
#   16.19    0.28   16.51
system.time(yRowMean <- rowMeans(x))
#    user  system elapsed 
#    0.02    0.00    0.02
identical(yLoop,yApply,yRowMean)
# TRUE

コードが非常に遅い理由は、Gavin が指摘したように、ループの反復ごとに配列を大きくしているためです。ループの前に配列全体を事前に割り当てると、大幅なスピードアップが見られます。

于 2011-03-28T14:22:11.343 に答える