Reputation: 307
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.
Upvotes: 1
Views: 185
Reputation: 174478
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)
Upvotes: 3
Reputation: 5673
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.
Upvotes: 2