Abdel
Abdel

Reputation: 6116

Make plots in a for loop in R with spplot

I'm having a little trouble programming stuff in R that I would normally do in a for loop in another language...

I am now trying to make a plot using spplot from the sp package (it's a chloropleth map), but I want to do it for a bunch of variables. In a for loop, I would program it like this:

for (TRAIT in c("height","bmi","whr","body_fat","income")){
pdf("plot_of_TRAIT.pdf")
spplot(MyData, "TRAIT", col.regions = my.palette, cuts = 8, lwd = 0.5)
dev.off()
}

where each instance of TRAIT should be replaced by the variables I give to the for loop (so in the filename of the pdf, and as an argument in the spplot command). Now, obviously this code does not work, but how would one go about doing this in R?

UPDATE:

I got the code to create different pdf files, but the spplot command still will not work. It creates empty pdf files:

for (TRAIT in c("height","bmi","whr","body_fat","income")){
outfile <- paste0("plot_of_", TRAIT, ".pdf")
pdf(outfile)
spplot(MyData, TRAIT, col.regions = my.palette, cuts = 8, lwd = 0.5)
dev.off()
}

If I run the exact same code outside of the for loop like this:

pdf("plot_of_height.pdf")
spplot(MyData, "height", col.regions = my.palette, cuts = 8, lwd = 0.5)
dev.off()

it works fine and I get the desired plot in the file plot_of_height.pdf.

UPDATE 2: This seems to be an issue with spplot. If I run this:

TRAIT <- "height"
pdf("plot_of_height.pdf")
spplot(MyData, TRAIT, col.regions = my.palette, cuts = 8, lwd = 0.5)
dev.off()

I get the following error:

Error in [.data.frame(obj@data, zcol) : undefined columns selected

Upvotes: 2

Views: 815

Answers (2)

Eumenedies
Eumenedies

Reputation: 1688

Without looking at your data, I cannot say why you have the undefined column error. Replicating your 'UPDATE 2' code with the meuse dataset does not throw the same error for me:


library(sp)
demo(meuse, ask = FALSE, echo = FALSE)
TRAIT <- "copper"
my.palette <- c("black", "red", "green", "blue")
spplot(meuse, TRAIT, col.regions = my.palette, cuts = 8, lwd = 0.5)

As for the first case of your question: spplot (much like ggplot) won't output anything to the device from within a loop unless explicitly printed. Basically you are opening a pdf file, creating the plot but not saving it to the pdf file, then

The following code should work for you:

for (TRAIT in c("height","bmi","whr","body_fat","income")){
    outfile <- paste0("plot_of_", TRAIT, ".pdf")
    pdf(outfile)
    print(spplot(MyData, TRAIT, col.regions = my.palette, cuts = 8, lwd = 0.5))
    dev.off()
}

I tested it using the Meuse dataset and it worked fine there:

library(sp)
demo(meuse, ask = FALSE, echo = FALSE)
my.palette <- c("black", "red", "green", "blue")
for(TRAIT in c("cadmium", "copper", "lead", "zinc")){
  outfile <- paste0("plot_of_", TRAIT, ".pdf")
  pdf(outfile)
  print(spplot(meuse, TRAIT, col.regions = my.palette, cuts = 8, lwd = 0.5))
  dev.off()
}

Giving me 4 distinct pdfs, each containing the spatial plot of the corresponding variable.

Upvotes: 1

neilfws
neilfws

Reputation: 33802

You need to construct the output file name using the variable.

For example:

outfile <- paste0("plot_of_", TRAIT, ".pdf")
pdf(outfile)

For spplot you probably need to use TRAIT (no quotes).

EDIT:

Since spplot(zcol = ... can be a column number, I wonder if this might work?

traits <- c("height","bmi","whr","body_fat","income")
for(i in 1:length(traits)) {
  pdf(paste0("plot_of_", traits[i], ".pdf")
  spplot(MyData, i, col.regions = my.palette, cuts = 8, lwd = 0.5)
  dev.off()
}

Upvotes: 2

Related Questions