简体   繁体   中英

R: How to plot 4 graphs using a loop statement with the plot function

I have the following code which creates a plot for, the data is located here Data

data<-lidar
x<-lidar$range
y<-lidar$logratio
h<-20
par(mfrow=c(2,2))

r<-max(x)-min(x)
bn<-ceiling(r/h)
binwidth=c(5,10,30,100)
  
  
#Creates a matrix to handle the data of same length
W<-matrix(nrow=length(x),ncol=bn)
for (j in 1:bn){
  for (i in 1:length(x)){
    if (x[i]>=(min(x)+(j-1)*h) && x[i]<=(min(x)+(j)*h)){W[i,j]=1}
    else {W[i,j]=0}
  }
}

#Sets up the y-values of the bins
fit<-rep(0,bn)
for (j in 1:bn){
  fit[j]<- sum(y*W[,j]/sum(W[,j]))
}

#Sets up the x values of the bins
t<-numeric(bn)
for (j in 1:bn){
  t[j]=(min(x)+0.5*h)+(j-1)*h
}

plot(x,y)
lines(t,fit,type = "S", col = 1, lwd = 2)

This creates a single plot in the left corner of a page since I have

par(mfrow=c(2,2))

Is there a way to create a for statement that will plot 4 graphs for me on that one page using h values of 5,10,30,100 (The values provided by the variable binwidth) so I don't have to manually change my h value every time to reproduce a new plot so my final result appears like this,

在此处输入图片说明

Essentially I want to run the code 4 times with different values of h using another for statement that plots all 4 results without me changing h all the time. Any help or hints are greatly appreciated.

Here's a fully reproducible example that loads the data directly from the url then uses the apply family to iterate through the different plots

lidar <- read.table(paste0("http://www.stat.cmu.edu/%7Elarry",
                           "/all-of-nonpar/=data/lidar.dat"),
                    header = TRUE)

par(mfrow = c(2, 2))

breaks <- lapply(c(5, 10, 30, 100), function(i) {
                   val <- seq(min(lidar$range), max(lidar$range), i)
                   c(val, max(val) + i)})

means <- lapply(breaks, function(i) {
            vals <- tapply(lidar$logratio, 
                    cut(lidar$range, breaks = i, include.lowest = TRUE), mean)
            c(vals[1], vals)})

invisible(mapply(function(a, b) {
  plot(lidar$range, lidar$logratio)
  lines(a, b, type = "S", lwd = 2)
  }, breaks, means))

在此处输入图片说明

Created on 2020-09-25 by the reprex package (v0.3.0)

Answering directly your question: keep the same other parameters:

data<-lidar
x<-lidar$range
y<-lidar$logratio
h<-20
par(mfrow=c(2,2))

r<-max(x)-min(x)
bn<-ceiling(r/h)
binwidth=c(5,10,30,100)

do a plot function (not necessary, but good practice)

doplot = function(h){
  #Creates a matrix to handle the data of same length
  W<-matrix(nrow=length(x),ncol=bn)
  for (j in 1:bn){
    for (i in 1:length(x)){
      if (x[i]>=(min(x)+(j-1)*h) && x[i]<=(min(x)+(j)*h)){W[i,j]=1}
      else {W[i,j]=0}
    }
  }
  
  #Sets up the y-values of the bins
  fit<-rep(0,bn)
  for (j in 1:bn){
    fit[j]<- sum(y*W[,j]/sum(W[,j]))
  }
  
  #Sets up the x values of the bins
  t<-numeric(bn)
  for (j in 1:bn){
    t[j]=(min(x)+0.5*h)+(j-1)*h
  }

  
  plot(x,y)
  lines(t,fit,type = "S", col = 1, lwd = 2)
}

and then loop on the h parameter

for(h in c(5,10,30,100)){
  doplot(h)
}

A general comment: you could gain a lot learning how to use the data.frames, a bit of dplyr or data.table and ggplot2 to do that. I feels that you could replicate your entire code + plots in 10 more comprehensible lines.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM