total tamaño que paquete indica identificador flujo ejemplo datagrama cuál campo cabecera r dataframe rows

tamaño - identificador de flujo



Para cada fila en un datagrama R (8)

Tengo un marco de datos, y para cada fila en ese marco de datos tengo que hacer algunas búsquedas complicadas y anexar algunos datos a un archivo.

El marco de datos contiene resultados científicos para pozos seleccionados de placas de 96 pozos utilizados en investigación biológica, así que quiero hacer algo como:

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) }

En mi mundo de procedimientos, haría algo como:

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

¿Cuál es la "forma R" de hacer esto?


Bueno, como pediste R equivalente a otros idiomas, intenté hacer esto. Parece que funciona aunque realmente no he visto qué técnica es más eficiente en 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

Sin embargo, para las columnas categóricas, obtendría un Marco de datos que podría encasillar utilizando as.character () si fuera necesario.


Creo que la mejor manera de hacer esto con R básica es:

for( i in rownames(df) ) print(df[i, "column1"])

La ventaja con respecto al enfoque for (i en 1: nrow (df)) es que no tiene problemas si df está vacío y nrow (df) = 0.


Primero, el punto de Jonathan sobre la vectorización es correcto. Si su función getWellID () está vectorizada, entonces puede omitir el ciclo y simplemente usar cat o write.csv:

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

Si getWellID () no está vectorizado, entonces la recomendación de Jonathan de usar by o la sugerencia de apply de knguyen debería funcionar.

De lo contrario, si realmente quieres usar, puedes hacer algo como esto:

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

También puede intentar usar el paquete foreach , aunque requiere que se familiarice con esa sintaxis. Aquí hay un ejemplo simple:

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

Una última opción es usar una función del paquete plyr , en cuyo caso la convención será muy similar a la función apply.

library(plyr) ddply(dataFrame, .(x), function(x) { # do stuff })


Puede usar la función by() :

by(dataFrame, 1:nrow(dataFrame), function(row) dostuff)

Pero iterar sobre las filas directamente como este rara vez es lo que desea; deberías tratar de vectorizar en su lugar. ¿Puedo preguntar qué está haciendo el trabajo real en el ciclo?


Puede usar la función by_row del by_row del paquete para esto:

myfn <- function(row) { #row is a tibble with one row, and the same #number of columns as the original df #If you''d rather it be a list, you can use as.list(row) } purrrlyr::by_row(df, myfn)

De forma predeterminada, el valor devuelto de myfn se coloca en una nueva columna de lista en el df llamado .out .

Si este es el único resultado que desea, puede escribir purrrlyr::by_row(df, myfn)$.out


Puedes probar esto, usando la función 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'')


Tenía curiosidad sobre el rendimiento en el tiempo de las opciones no vectorizadas. Para este propósito, he usado la función f definida por knguyen

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) }

y un marco de datos como el de su ejemplo:

n = 100; #number of rows for the data frame d <- data.frame( name = LETTERS[ sample.int( 25, n, replace=T ) ], plate = paste0( "P", 1:n ), value1 = 1:n, value2 = (1:n)*10 )

Incluí dos funciones vectorizadas (seguramente más rápidas que las otras) para comparar el enfoque cat () con un write.table () uno ...

library("ggplot2") library( "microbenchmark" ) library( foreach ) library( iterators ) tm <- microbenchmark(S1 = apply(d, 1, f, output = ''outputfile1''), S2 = for(i in 1:nrow(d)) { row <- d[i,] # do stuff with row f(row, ''outputfile2'') }, S3 = foreach(d1=iter(d, by=''row''), .combine=rbind) %dopar% f(d1,"outputfile3"), S4= { print( paste(wellID=rep(1,n), d[,3], d[,4], sep=",") ) cat( paste(wellID=rep(1,n), d[,3], d[,4], sep=","), file= ''outputfile4'', sep=''/n'',append=T, fill = F) }, S5 = { print( (paste(wellID=rep(1,n), d[,3], d[,4], sep=",")) ) write.table(data.frame(rep(1,n), d[,3], d[,4]), file=''outputfile5'', row.names=F, col.names=F, sep=",", append=T ) }, times=100L) autoplot(tm)

La imagen resultante muestra que aplicar da el mejor rendimiento para una versión no vectorizada, mientras que write.table () parece superar a cat ().


Yo uso esta sencilla función de utilidad:

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

O una forma más rápida, menos clara:

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

Esta función simplemente divide un data.frame en una lista de filas. Entonces puedes hacer un "para" normal sobre esta lista:

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

Su código de la pregunta funcionará con una modificación mínima:

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) }