Tenho um dataframe, e para cada fila desse dataframe tenho de fazer algumas pesquisas complicadas e anexar alguns dados a um ficheiro.
O dataFrame contém resultados científicos para poços seleccionados de 96 placas de poços utilizados na investigação biológica, por isso quero fazer algo do género:
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)
}
No meu mundo processual, I'faria algo do género:
for (row in dataFrame) {
#look up stuff using data from the row
#write stuff to the file
}
O que é o "R way" para fazer isto?
Pode utilizar a função by()``:
by(dataFrame, 1:nrow(dataFrame), function(row) dostuff)
Mas uma iteração sobre as filas directamente como esta raramente é o que se pretende; em vez disso, deve-se tentar vectorizar. Posso perguntar o que é que o trabalho real no laço está a fazer?
Pode tentar isto, utilizando a função aplicar()
> 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')
Primeiro, Jonathan' o ponto sobre vectorização está correcto. Se a sua função getWellID() estiver vectorizada, então pode saltar o laço e usar apenas cat ou write.csv:
write.csv(data.frame(wellid=getWellID(well$name, well$plate),
value1=well$value1, value2=well$value2), file=outputFile)
Se getWellID() is't vectorizada, então a recomendação de Jonathan's de utilizar "by" ou knguyen's sugestão de "aplicar" deve funcionar.
Caso contrário, se quiser realmente utilizar "para", pode fazer algo como isto:
for(i in 1:nrow(dataFrame)) {
row <- dataFrame[i,]
# do stuff with row
}
Também pode tentar utilizar o pacote "para cada um", embora isso exija que se familiarize com essa sintaxe. Aqui's um exemplo simples:
library(foreach)
d <- data.frame(x=1:10, y=rnorm(10))
s <- foreach(d=iter(d, by='row'), .combine=rbind) %dopar% d
Uma última opção é utilizar uma função do pacote plyr
, caso em que a convenção será muito semelhante à função aplicável.
library(plyr)
ddply(dataFrame, .(x), function(x) { # do stuff })