Tengo un marco de datos, y para cada fila en ese marco de datos tengo que hacer algunas búsquedas complicadas y agregar algunos datos a un archivo.
El DataFrame contiene resultados científicos para pozos seleccionados de placas de 96 pocillos utilizados en investigación biológica, por lo 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 procesal, 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" para hacer esto?
Respuestas:
Puedes probar esto, usando la
apply()
funciónfuente
x
) es un vector. Es por esto que el ejemplo anterior tiene que usar índices numéricos; el enfoque by () le brinda un marco data.frame, que hace que su código sea más robusto.wellName <- x[1]
también podría serwellName <- x["name"]
.Puedes usar la
by()
función:Pero iterar sobre las filas directamente así rara vez es lo que quieres; deberías tratar de vectorizar en su lugar. ¿Puedo preguntar qué está haciendo el trabajo real en el bucle?
fuente
1:0
no está vacíoseq_len(nrow(dataFrame))
en lugar de1:nrow(dataFrame)
.dostuff
esta respuesta astr(row)
Verás varias líneas impresas en la consola que comienzan con "'data.frame': 1 obs de x variables". Pero tenga cuidado, cambiardostuff
arow
no devuelve un objeto data.frame para la función externa en su conjunto. En su lugar, devuelve una lista de marcos de datos de una fila.Primero, el punto de Jonathan sobre la vectorización es correcto. Si su función getWellID () está vectorizada, puede omitir el ciclo y simplemente usar cat o write.csv:
Si getWellID () no está vectorizado, entonces la recomendación de Jonathan de usar
by
o la sugerencia de knguyenapply
debería funcionar.De lo contrario, si realmente quieres usar
for
, puedes hacer algo como esto:También puede intentar usar el
foreach
paquete, aunque requiere que se familiarice con esa sintaxis. Aquí hay un ejemplo simple:Una opción final es usar una función fuera del
plyr
paquete, en cuyo caso la convención será muy similar a la función de aplicación.fuente
mapply(getWellId, well$name, well$plate)
.foreach
- Voy a sacar el máximo provecho de eso.Creo que la mejor manera de hacer esto con R básica es:
La ventaja sobre el
for( i in 1:nrow(df))
enfoque es que no se mete en problemas sidf
está vacío ynrow(df)=0
.fuente
Yo uso esta sencilla función de utilidad:
O una forma más rápida y menos clara:
Esta función simplemente divide un data.frame en una lista de filas. Entonces puede hacer un "for" normal sobre esta lista:
Su código de la pregunta funcionará con una modificación mínima:
fuente
lapply
itera sobre las columnas de todo el conjunto de datosx
, dando a cada columna el nombrec
y luego extrayendo lai
entrada th de ese vector de columna. ¿Es esto correcto?wellName <- as.character(well$name)
.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
y un marco de datos como el de su ejemplo:
Incluí dos funciones vectorizadas (seguramente más rápido que las demás) para comparar el enfoque cat () con uno write.table () ...
La imagen resultante muestra que apply ofrece el mejor rendimiento para una versión no vectorizada, mientras que write.table () parece superar a cat ().
fuente
Puede usar la
by_row
función del paquetepurrrlyr
para esto:Por defecto, el valor devuelto desde
myfn
se coloca en una nueva columna de lista en el df llamado.out
.Si esta es la única salida que deseas, podrías escribir
purrrlyr::by_row(df, myfn)$.out
fuente
Bueno, como pediste R equivalente a otros idiomas, traté de hacer esto. Parece funcionar, aunque realmente no he visto qué técnica es más eficiente en R.
Sin embargo, para las columnas categóricas, obtendría un Marco de datos que podría escribir utilizando as.character () si es necesario.
fuente