BDM
BDM

Reputation: 624

How to create a loop in R to iteratively plot elements of an array?

I am trying the create a loop to extract data from an array created previously, so that I can then use the extracted data to generate a line plot.

So far I have been doing it manually by using:

allweek1<-(data.frame(t_weekmean[,,1])) #which selects the date and generates the data frame I want to later format the date using
week1<-stack(allweek1) #and then plot it using
plot(week1$values,type="n", xlim=c(0,2),xlab="Weight (gr)",ylab="Rate (umol/L*gr)",main="All individuals and Treatments at all times")
lines(week1$values[week1$ind=="X9"]~x,type="o",col="red")
lines(week1$values[week1$ind=="X12"]~x,type="o",col="blue")
lines(week1$values[week1$ind=="X15"]~x,type="o",col="green")
lines(week1$values[week1$ind=="X18"]~x,type="o",col="purple").

I know there has to be a way of making this into a loop, for this example I am giving just two weeks but my data goes up to 30, and doing it manually will be messy and easy to have mistakes.

This is the starting array that I have:

, , Week = 1

        Temp
variable       9      12      15      18
    X0   100.000 100.000 100.000 100.000
    X0.5  98.855  98.591  98.357  99.003
    X1    98.004  97.804  97.638  98.299
    X1.5  95.953  96.999  96.810  97.555
    X2    95.235  96.078  95.346  96.665

, , Week = 2

        Temp
variable       9      12      15      18
    X0   100.000 100.000 100.000 100.000
    X0.5  99.137  99.035  97.883  99.055
    X1    98.420  98.298  96.459  97.765
    X1.5  97.939  97.181  94.406  96.546
    X2    96.998  96.237  91.906  95.263

The following data frame which is then converted to a stack version:

          X9     X12     X15     X18
X0   100.000 100.000 100.000 100.000
X0.5  98.855  98.591  98.357  99.003
X1    98.004  97.804  97.638  98.299
X1.5  95.953  96.999  96.810  97.555
X2    95.235  96.078  95.346  96.665

and then the code for plotting is used.

Upvotes: 4

Views: 3228

Answers (2)

Marek
Marek

Reputation: 50704

Sounds like task for lattice:

X <- as.data.frame(as.table(t_weekmean), stringsAsFactors=FALSE, responseName="values")
X$variable <- as.numeric(gsub("^X","",X$variable))
X$Temp <- as.numeric(X$Temp)

require(lattice)
xyplot(values~variable|Week, groups=Temp, X, type="o", as.table=TRUE,
    xlab="Weight (gr)", ylab="Rate (umol/L*gr)", main="All individuals and Treatments at all times"
)

Multi-plot in Lattice

I recreate your data as:

t_weekmean <- structure(c(100, 98.855, 98.004, 95.953, 95.235, 100, 98.591, 97.804, 96.999, 96.078, 100, 98.357, 97.638, 96.81, 95.346, 100, 99.003, 98.299, 97.555, 96.665, 100, 99.137, 98.42, 97.939, 96.998, 
100, 99.035, 98.298, 97.181, 96.237, 100, 97.883, 96.459, 94.406, 91.906, 100, 99.055, 97.765, 96.546, 95.263, 99.9889679441867, 
98.8470416045204, 98.010997102523, 95.9636806506725, 95.235986063534, 100.00797414162, 98.5968712619705, 97.7984016535804, 96.9904933552904, 
96.0816877686208, 99.9946318131395, 98.3568674165109, 97.6357767063124, 96.8119443900658, 95.3441814383421, 99.989633272252, 99.0037062049508, 
98.3034580102509, 97.5568340624981, 96.6615796074679, 100.000379644977, 99.1375077671092, 98.4187321210541, 97.9350205929782, 97.0006243532971, 
100.003971157774, 99.0316462150477, 98.298322594611, 97.1782003010139, 96.239865449585, 100.002464797458, 97.8810655647218, 96.4592857614756, 
94.4099917372801, 91.9025173998885, 100.003642400375, 99.0529984607268, 97.76302246443, 96.5426428484451, 95.2658935513329),
.Dim = c(5L, 4L, 4L), .Dimnames = structure(list(variable = c("X0", "X0.5", "X1", "X1.5", "X2"),
Temp = c("9", "12", "15", "18"), Week = c("1", "2", "3", "4")), .Names = c("variable", "Temp", "Week"))
)

Upvotes: 3

Nick Sabbe
Nick Sabbe

Reputation: 11956

If you use plyr, you can do this with a_ply:

a_ply(t_weekmean, 3, function(arrayforcurweek){
allweek1<-(data.frame(arrayforcurweek)) #which selects the date and generates the data frame I want to later format the date using
week1<-stack(allweek1) #and then plot it using
plot(week1$values,type="n", xlim=c(0,2),xlab="Weight (gr)",ylab="Rate (umol/L*gr)",main="All individuals and Treatments at all times")
lines(week1$values[week1$ind=="X9"]~x,type="o",col="red")
lines(week1$values[week1$ind=="X12"]~x,type="o",col="blue")
lines(week1$values[week1$ind=="X15"]~x,type="o",col="green")
lines(week1$values[week1$ind=="X18"]~x,type="o",col="purple")
})

Like, this, you will only ever see the last graph, because the rest is typically overwritten. So you may want to add a layout statement, or provide a pause between the graphs etc.

OK, some more information as per your comment:

a_ply takes 3 parameters here: first an array on which to perform things, next a 'margin', meaning: over which of the dimensions should I iterate (this is the 'hidden' loop), and finally a function to perform on all the parts.

So what happens: a_ply takes all possible values for the third dimension of your array (because margin==3), and runs over them (you could see this as an indexer i in a for loop). Then it takes the part of your array for each of these values (kind of like t_weekmean[,,i]), and feeds this to the function that is the third parameter (so within this function, the consecutive marginal arrays will be known as arrayforcurweek).

The problem with this way of working, is that the graphs are made in quick succession, so if you simply run this code and view the image window, you should only see the graph for the last value of your third dimension. If you want to see all of them next to one another (although this would cause tiny graphs), you would prefix this with something like: layout(matrix(1:30), nrow=6) This will cause the screen to be split up in 30, so that each plot gets its own part of the full screen.

I believe, if you write immediately to a pdf or similar, that you don't require this, but I don't have experience with that.

Does this help you along?

Upvotes: 3

Related Questions