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:0no está vacíoseq_len(nrow(dataFrame))en lugar de1:nrow(dataFrame).dostuffesta 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, cambiardostuffarowno 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
byo la sugerencia de knguyenapplydebería funcionar.De lo contrario, si realmente quieres usar
for, puedes hacer algo como esto:También puede intentar usar el
foreachpaquete, aunque requiere que se familiarice con esa sintaxis. Aquí hay un ejemplo simple:Una opción final es usar una función fuera del
plyrpaquete, 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 sidfestá 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
lapplyitera sobre las columnas de todo el conjunto de datosx, dando a cada columna el nombrecy luego extrayendo laientrada 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_rowfunción del paquetepurrrlyrpara esto:Por defecto, el valor devuelto desde
myfnse 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)$.outfuente
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