Foro de debate

Simplificación de tres bucles anidados y gráfica múltiple

Simplificación de tres bucles anidados y gráfica múltiple

de Rubén Gómez -
Número de respuestas: 3
Hola:

Para agrupar datos a partir de un conjunto de los mismos existentes en un data.frame, estoy utilizando tres bucles for anidados. Como todavía soy novato con R es lo mejor que he sido capaz de hacer, pero me gustaría saber si es posible simplificar esos tres bucles anidados.

La otra duda es que, a partir del nuevo objeto data.frame creado con los bucles for quiero crear un gráfico de cajas (boxplot) para cada una de las filas, pero que quede en una sola «pantalla», por ahora no lo he conseguido.

Entro a exponer ejemplo y código.

Tengo un objeto data.frame de este tipo:

Mes - Dirección - Clase 1 - Clase 2 - Clase 3
1 - Norte - 10 - 30 - 60
1 - Este - 15 - 35 - 50
1 - Sur - 25 - 25 -50
1 - Oeste - 35 - 35 - 30

y así para los doce meses del año. A partir de este objeto, quiero sacar un conjunto de datos de este tipo:

Norte, Clase 1: Mes 1, Mes 2, Mes 3...
Norte, Clase 2: Mes 1, Mes 2, Mes 3...

Lo he logrado con este código:

######## Código ##########

vuelta=1

for (i in 1:length(Aero.direcciones)) {

for (j in 1:length(Aero.clases)) {

var.interna=rep(0,12)

# print(Aero.clases[j])

for (z in 1:12) {

var.interna[z]=Aero.vientos[which(Aero.vientos[,2]==
Aero.direcciones[i])[z],Aero.clases[j]]


} #Fin del bucle de los meses. Cambia de clase.

var.interna[which(is.na(var.interna))]=0

if (sum(var.interna) != 0) {

vuelta=vuelta+1

Aero.conj.datos[vuelta,]=data.frame(
matrix(var.interna,nrow=1,byrow=T),row.names=paste(
Aero.direcciones[i],"-",Aero.clases[j]
)
)
} # Fin del if

# print(paste("Vuelta dentro clases",vuelta))

} # Fin del bucle de las clases. Cambia de dirección.

# print(paste("Dirección",Aero.direcciones[i],"Vuelta",vuelta))
}

rm(i,j,z,var.interna,vuelta)

######### Fin de código ######

Esta línea:

var.interna[which(is.na(var.interna))]=0

es porque en el objeto original los datos que aparecen como NA son, en realidad, 0. Como en algunas ocasiones la dirección-clase es 0 para todos los meses, directamente lo elimino con el if siguiente.

Aclaro que en el data.frame que se crea (Aero.conj.datos) empiezo en [2,] porque previamente ya tengo una línea creada con una situación especial.

¿Habría alguna forma de simplificarlo?

En cuanto a la gráfica, estoy utilizando esto:

sapply(1:73, function(x) boxplot(as.vector(as.matrix(Aero.conj.datos[x,]))))

Pero, aunque crea los gráficos de cajas que persigo, no me lo hace todo en la misma «pantalla» que es lo que quiero.

¿Alguna forma de poder obtener ese gráfico?

Gracias por adelantado.

Un saludo.

R. Gómez
En respuesta a Rubén Gómez

Re: Simplificación de tres bucles anidados y gráfica múltiple

de Manuel Muñoz Márquez -
Hola Rubén:

No he intentado hacer lo que propones pero sospecho que la solución a tu problema está en la instrucción:
reshape

Con respecto a lo de los gráficos no me queda muy claro qué quieres hacer. Si simplemente es pintar 12 gráficos juntos puedes la instrucción:
par(mfrow=c(4,3))
te divide la ventana gráfica en 12 partes para que luego pintes 12 gráficos. Pero esto me parece poco útil, tendrás problemas de visibilidad y de diferencia entre las escalas de los diferentes gráficos.

¿Te has planteado hacer un único diagrama con barras apiladas o agrupadas?

Saludos.
En respuesta a Manuel Muñoz Márquez

Re: Simplificación de tres bucles anidados y gráfica múltiple

de Rubén Gómez -
Hola Manuel:

Ante todo, gracias por tu respuesta.

Le echaré un vistazo a reshape, parece que puede ser útil para «reorganizar» tablas de datos.

La verdad es que quería ver como lo hubiese resuelto vosotros, los que sabéis ^_^ por aquello del ver-leer código para aprender y tal.

De hecho, todavía tengo problemas con algunas cosas y suelo recurrir a bucles. Ahora mismo, por ejemplo, estoy intentado hacer una resta fila a fila entre las dos primeras columnas de una matriz, y nada:

sapply(1:10,function(x) tabla[x,1]-tabla[x,2])

argumento no-numérico para operador binario
Calls: sapply -> lapply -> FUN

apply(tabla[,1:2],2,function(x) tabla[,1]-tabla[,2])

argumento no-numérico para operador binario
Calls: apply -> FUN

Total, que de nuevo voy a tener que hacer un bucle, y, por lo que leo, los bucles no son «la forma habitual» de hacer las cosas con R.

Sobre el tema de los gráficos:

---- Respuesta de Manuel ----

Con respecto a lo de los gráficos no me queda muy claro qué quieres hacer. Si simplemente es pintar 12 gráficos juntos puedes la instrucción:
par(mfrow=c(4,3))
te divide la ventana gráfica en 12 partes para que luego pintes 12 gráficos. Pero esto me parece poco útil, tendrás problemas de visibilidad y de diferencia entre las escalas de los diferentes gráficos.

¿Te has planteado hacer un único diagrama con barras apiladas o agrupadas?

------------ Fin de respuesta ----

(¿Como se hace en moodle para citar una respuesta?, «quote» no funciona)

Si me he planteado hacer un único diagrama, pero no lo consigo:

bwplot(row.names(tabla)~tabla)

me saca una cosa rara, así que «he tirado por lo facil», que es dividir la «ventana» en varias partes iguales y dibujar ahí los distintos gráficos.

Como el «par» que me indicas no lo controlo en exceso, utilicé «layout»

ventana=matrix(c(1:10),nrow=2,ncol=5,byrow=T)
layout(ventana)

Como son muchos gráficos he realizado varias «capturas» y andando.

No queda todo lo bien que me gustaría, pero por el momento no tengo mucho más tiempo para poder dedicarle a esto.

Bueno, gracias de nuevo.

Un saludo.

R. Gómez
En respuesta a Rubén Gómez

Re: Simplificación de tres bucles anidados y gráfica múltiple

de Manuel Muñoz Márquez -
Hola Rubén:

Con respecto a restar dos columna (si no te he entendido mal) es fácil:
> m = diag(3)
> m
[,1] [,2] [,3]
[1,] 1 0 0
[2,] 0 1 0
[3,] 0 0 1
> m[,1]-m[,2]
[1] 1 -1 0

El resultado debería ser una columna, pero R convierte automáticamente cualquier matriz con una fila o una columna a vector.

Si lo quieres hacer con todas las columnas a la vez:
>m[,-3] - m[,-1]
[,1] [,2]
[1,] 1 0
[2,] -1 1
[3,] 0 -1

o equivalente
>m[,c(1,2)]-m[,c(2,3)]

Con respecto a los gráficos layout y lo que te comenté del par hacen la misma función pero usando librerías distintas. Dependiendo del gráfico a dibujar puede ser necesario usar una u otra. Aquí no te puedo ayudar más, sigo sin tener muy claro qué es lo que quieres hacer.

Por último con respecto a la pregunta de moodle, yo también me la he planteado y no he encontrado la forma de hacerlo. Tal vez en la versión 2.0 de moodle sea posible.

Saludos.