189

データフレームがあり、そのデータフレームの各行に対して、複雑な検索を行い、データをファイルに追加する必要があります。

dataFrame には、生物学的研究で使用される 96 ウェル プレートから選択されたウェルの科学的結果が含まれているため、次のようなことをしたいと考えています。

for (well in dataFrame) {
  wellName <- well$name    # string like "H1"
  plateName <- well$plate  # string like "plate67"
  wellID <- getWellID(wellName, plateName)
  cat(paste(wellID, well$value1, well$value2, sep=","), file=outputFile)
}

私の手続き型の世界では、次のようなことをします。

for (row in dataFrame) {
    #look up stuff using data from the row
    #write stuff to the file
}

これを行うための「Rの方法」とは何ですか?

4

9 に答える 9

124

by()次の関数を使用できます。

by(dataFrame, seq_len(nrow(dataFrame)), function(row) dostuff)

しかし、このように行を直接反復処理することは、めったに必要ありません。代わりにベクトル化を試みる必要があります。ループ内の実際の作業は何をしているのですか?

于 2009-11-09T05:54:32.277 に答える
108

apply()関数を使用して、これを試すことができます

> d
  name plate value1 value2
1    A    P1      1    100
2    B    P2      2    200
3    C    P3      3    300

> f <- function(x, output) {
 wellName <- x[1]
 plateName <- x[2]
 wellID <- 1
 print(paste(wellID, x[3], x[4], sep=","))
 cat(paste(wellID, x[3], x[4], sep=","), file= output, append = T, fill = T)
}

> apply(d, 1, f, output = 'outputfile')
于 2009-11-09T14:02:05.553 に答える
102

まず、ベクトル化に関するジョナサンの指摘は正しいです。getWellID() 関数がベクトル化されている場合は、ループをスキップして cat または write.csv のみを使用できます。

write.csv(data.frame(wellid=getWellID(well$name, well$plate), 
         value1=well$value1, value2=well$value2), file=outputFile)

getWellID() がベクトル化されていない場合は、Jonathan の使用の推奨byまたは knguyen の提案がapply機能するはずです。

それ以外の場合、本当に を使用したい場合はfor、次のようにすることができます。

for(i in 1:nrow(dataFrame)) {
    row <- dataFrame[i,]
    # do stuff with row
}

パッケージを使用することもできますがforeach、その構文に慣れる必要があります。簡単な例を次に示します。

library(foreach)
d <- data.frame(x=1:10, y=rnorm(10))
s <- foreach(d=iter(d, by='row'), .combine=rbind) %dopar% d

最後のオプションは、plyrパッケージ外の関数を使用することです。この場合、規則は適用関数と非常に似ています。

library(plyr)
ddply(dataFrame, .(x), function(x) { # do stuff })
于 2009-11-09T14:04:18.763 に答える
20

この単純なユーティリティ関数を使用します。

rows = function(tab) lapply(
  seq_len(nrow(tab)),
  function(i) unclass(tab[i,,drop=F])
)

または、より速く、あまり明確でないフォーム:

rows = function(x) lapply(seq_len(nrow(x)), function(i) lapply(x,"[",i))

この関数は、data.frame を行のリストに分割するだけです。次に、このリストに対して通常の「for」を作成できます。

tab = data.frame(x = 1:3, y=2:4, z=3:5)
for (A in rows(tab)) {
    print(A$x + A$y * A$z)
}        

質問のコードは、最小限の変更で機能します。

for (well in rows(dataFrame)) {
  wellName <- well$name    # string like "H1"
  plateName <- well$plate  # string like "plate67"
  wellID <- getWellID(wellName, plateName)
  cat(paste(wellID, well$value1, well$value2, sep=","), file=outputFile)
}
于 2015-08-27T18:44:18.477 に答える
2

さて、あなたが他の言語に相当するRを求めたので、私はこれをやろうとしました。Rでどの手法がより効率的であるかを実際に調べたことはありませんが、うまくいくようです.

> myDf <- head(iris)
> myDf
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1          5.1         3.5          1.4         0.2  setosa
2          4.9         3.0          1.4         0.2  setosa
3          4.7         3.2          1.3         0.2  setosa
4          4.6         3.1          1.5         0.2  setosa
5          5.0         3.6          1.4         0.2  setosa
6          5.4         3.9          1.7         0.4  setosa
> nRowsDf <- nrow(myDf)
> for(i in 1:nRowsDf){
+ print(myDf[i,4])
+ }
[1] 0.2
[1] 0.2
[1] 0.2
[1] 0.2
[1] 0.2
[1] 0.4

ただし、カテゴリ列の場合は、必要に応じて as.character() を使用して型キャストできるデータ フレームをフェッチします。

于 2015-02-13T15:04:03.127 に答える