loop error - plot.new has not been called yet - r

I want to simulate stock paths. I have simulated 1000 paths with 22 trading days (1 starting value). Now I want to include it into my presentation, but animated, so I need the png files.
I want to create 1000 png files, starting with the first stock path, then the second and so on.
So I start with the first path, add a second to the plot, add the third and so on, so at the end I have a plot with 1000 simulations, here is my code:
for(i in 1:1000){
#jpeg(paste("1000s",i,".png",sep=""))
plot(c(1:23),matrix[,1],type="l",ylim=c(17,24))
lines(c(1:23),matrix[,i],type="l",col=i)
#dev.off()
}
Here is the problem, that each additional part disappears when the loop gets to the next value, so I tried:
plot(0,0 , xlim=c(1,23),ylim=c(17,24),xlab="",ylab="")
for(i in 1:1000){
jpeg(paste("1000s",i,".png",sep=""))
lines(c(1:23),matrix[,i],type="l",col=i)
dev.off()
}
(I know this is not a working example, but my problem is just a logical one with the loop) I get the following error message when I the last code: plot.new has not been called yet.
The matrix has 1000 columns and 23 row entries, this should be 1000 simulations of stock pathes for 22 trading days.
How can I change that the error does not appear anymore? Thanks!

Use two for loops. The outer loop will create each png/jpeg. The inner one will build up each individual plot.
for(i in 1:1000) {
jpeg(paste("1000s", i, ".png", sep=""))
plot(0, 0, xlim=c(1,23), ylim=c(17,24), xlab="", ylab="")
for(j in 1:i) {
lines(c(1:23), matrix[, j], col=j)
}
dev.off()
}

jpeg and plot both make new graphs. You just need lines calls in the loop, if you want the animation to build and not erase. One thing, lines doesn't need type = 'l'. That's it's default and the whole point of the command is that's it's default. If you wanted to plot points with it you might change the argument but otherwise just leave it out.

Related

How to make multiple plots with a for loop?

I was experimenting with the waffle package in r, and was trying to use a for loop to make multiple plots at once but was not able to get my code to work. I have a dataset with values for each year of renewables,and since it is over 40 years of data, was looking for a simple way to plot these with a for loop rather than manyally year by year. What am I doing wrong?
I have it from 1:16 as an experiment to see if it would work, although in reality I would do it for all the years in my dataset.
for(i in 1:16){
renperc<-islren$Value[i]
parts <- c(`Renewable`=(renperc), `Non-Renewable`=100-renperc)
waffle(parts, rows=10, size=1, colors=c("#00CC00", "#A9A9A9"),
title="Iceland Primary Energy Supply",
xlab=islren$TIME)
}
If I get your question correctly you want to plot all the 16 iterations in a same panel? You can parametrise your plot window to be divided into 16 smaller plots using par(mfrow = c(4,4)) (creating a 4 by 4 matrix and plotting into each cells recursively).
## Setting the graphical parameters
par(mfrow = c(4,4))
## Running the loop normally
for(i in 1:16){
renperc<-islren$Value[i]
parts <- c(`Renewable`=(renperc), `Non-Renewable`=100-renperc)
waffle(parts, rows=10, size=1, colors=c("#00CC00", "#A9A9A9"),
title="Iceland Primary Energy Supply",
xlab=islren$TIME)
}
If you need more plots (e.g. 40) you can increase the numbers in the graphical parameters (e.g. par(mfrow = c(6,7))) but that will create really tiny plots. One solution is to do it in multiple loops (for(i in 1:16); for(i in 17:32); etc.)
UPDATE: The code simply wasn't plotting anything when i tried putting in anything above one value (ex. 1:16) or a letter, both in terms of separate plots or many in one plot window (which I think perhaps waffle does not support in the same way as regular plots). In the end, I managed by making it into a function, although I'm still not sure why my original method wouldn't work if this did. See the code that worked below. I also tweaked it a bit, adding ggsave for example.
#function
waffling <- function(x){
renperc<-islren$Value[x]
parts <- c(`Renewable`=(renperc), `Non-Renewable`=100-renperc)
waffle(parts, rows=10, size=1, colors=c("#00CC00", "#A9A9A9"), title="",
xlab=islren$TIME[x])
ggsave(file=paste0("plot_", x,".png"))}
for(i in 1:57){
waffling(i)
}

How to output the label of points in scatterplot to bash console

I have a simple R-Script:
args <- commandArgs(TRUE)
inp <- read.csv(args[1],sep="\t",header=FALSE,stringsAsFactors=FALSE)
firstCol <- inp$V2
secondCol <- inp$V3
pdf(args[2])
plot(firstCol,secondCol,xlab="#",ylab="maxLength")
dev.off()
I run it from a bash script to generate a basic plot.
Now I want to use X11() to plot directly into a window and not into a PDF.
What I want now is to appear the label (in inp$V1) of every dot on the console when hovering over a point or klicking onto it.
How to do?
The identify function lets you click on points and it returns the index value for the points clicked on that could be used to subset a vector of labels.
For identification when hovering (instead of clicking) you can look at the HTKidentify function in the TeachingDemos package.
Edit
Here is an example using identify that may be more what you want (I tested it on windows, not unix/X11):
x <- runif(26)
y <- rnorm(26)
plot(x,y)
while(length(tmp <- identify(x,y, plot=FALSE, n=1))) {
cat(letters[tmp],'\n')
}
The plot=FALSE tells identify to not put the label on the plot and the n=1 tells it to return after you click on 1 point (the while goes back to identifying more points, but prints out the label immediately).
Obviously you would create other labels to use than just the letters.

plot multiple figures interactively with split.screen and hold one constant

I am using R to plot a multifgure image with interactive capability in one of them. I'm using split.screen to do this (as I tried unsuccesfuly to do it right with par() and base R graphics.
My goal is to hold the display of each screen(1) jth plot, while the screen(2) plot figure updates interactively k times..
But even though I set erase = FALSE or TRUE, each time it iterates through the subloop, the first plot is cleared and displays a blank image. Any ideas on how to hold the first plot image, each time the sub loop, k updates its graphics?
split.screen(figs=c(1,2),erase=TRUE)
for(j in 1:5){
screen(1)
plot(rnorm(3))
screen(2)
for(k in 1:5){
plot(rnorm(3))
par(ask=TRUE)
}
}
update from help.
These functions are totally incompatible with the other mechanisms for arranging plots on a device: par(mfrow), par(mfcol)'and'layout().
I guess that explains the par(ask=TRUE). I'm still interested if anyone can do this using par() and base graphics functions.
I couldn't find any par() variables that would explicitly specify one of the two screens to plot on at any step, while allowing par(ask=T) to update in a subloop, which is what split.screen() was able to do.
Give Hmisc::subplot a try:
## draw first plot
par(mfcol=c(1,2), xpd=NA)
plot(rnorm(3))
plot(1,1) # dummy plot
## update subplot k times
for(k in 1:5) {
rect(grconvertX(par("fin")[1], from="inches"),
grconvertY(0, from="inches"),
grconvertX(par("fin")[1]*2, from="inches"),
grconvertY(par("fin")[2], from="inches"), col="white", border=NA) ## cover-up
subplot( plot(rnorm(3)), 1, 1, size=par("pin") )
readline("Hit <Return> to see next plot: ")
}
Adding a flush.console() and Sys.sleep() should do it.
split.screen(figs=c(1,2),erase=TRUE)
for(j in 1:5){
screen(1)
plot(rnorm(3))
flush.console()
Sys.sleep(0.5)
for(k in 1:5){
screen(2)
plot(rnorm(3))
par(ask=TRUE)
flush.console()
Sys.sleep(0.5)
}
}
That will still suppress the par(ask=TRUE) as per the warnings, but it should prevent the first plot going blank whilst the second iterates.

R, graph of binomial distribution

I have to write own function to draw the density function of binomial distribution and hence draw
appropriate graph when n = 20 and p = 0.1,0.2,...,0.9. Also i need to comments on the graphs.
I tried this ;
graph <- function(n,p){
x <- dbinom(0:n,size=n,prob=p)
return(barplot(x,names.arg=0:n))
}
graph(20,0.1)
graph(20,0.2)
graph(20,0.3)
graph(20,0.4)
graph(20,0.5)
graph(20,0.6)
graph(20,0.7)
graph(20,0.8)
graph(20,0.9)
#OR
graph(20,scan())
My first question : is there any way so that i don't need to write down the line graph(20,p) several times except using scan()?
My second question :
I want to see the graph in one device or want to hit ENTER to see the next graph. I wrote
par(mfcol=c(2,5))
graph(20,0.1)
graph(20,0.2)
graph(20,0.3)
graph(20,0.4)
graph(20,0.5)
graph(20,0.6)
graph(20,0.7)
graph(20,0.8)
graph(20,0.9)
but the graph is too tiny. How can i present the graphs nicely with giving head line n=20 and p=the value which i used to draw the graph?[though it can be done by writing mtext() after calling the function graphbut doing so i have to write a similar line few times. So i want to do this including in function graph. ]
My last question :
About comment. The graphs are showing that as the probability of success ,p is increasing the graph is tending to right, that is , the graph is right skewed.
Is there any way to comment on the graph using program?
Here a job of mapply since you loop over 2 variables.
graph <- function(n,p){
x <- dbinom(0:n,size=n,prob=p)
barplot(x,names.arg=0:n,
main=sprintf(paste('bin. dist. ',n,p,sep=':')))
}
par(mfcol=c(2,5))
mapply(graph,20,seq(0.1,1,0.1))
Plotting base graphics is one of the times you often want to use a for loop. The reason is because most of the plotting functions return an object invisibly, but you're not interested in these; all you want is the side-effect of plotting. A loop ignores the returned obects, whereas the *apply family will waste effort collecting and returning them.
par(mfrow=c(2, 5))
for(p in seq(0.1, 1, len=10))
{
x <- dbinom(0:20, size=20, p=p)
barplot(x, names.arg=0:20, space=0)
}

plotting specific points within a spreadsheet in r

currently I am plotting 2000 some lines on a single plot in r. I am using the data from a spreadsheet which i cannot disclose due to sensitive information, but I'll try to illistrate how it is arranged.
x1/x1/x1/x1/x1/x1/etc.
y1/y1/y1/y1/y1/y1/etc.
x2/x2/x2/x2/x2/x2/etc.
y2/y2/y2/y2/y2/y2/etc.
...
x4436/x4436/x4436/etc.
y4436/y4436/y4436/etc.
where each x1,y1 is a point on a separate line. I need to plot a point on the endpoint of each line and I cannot seem to get my code to work. Currently I am using this to generate the points:
for (k in (1:2218)*2) {
q <- unlist(e_web_clear[2*k])
w <- unlist(e_web_clear[716])
points(w, q, col = "lightblue")
}
the way I imagined it, it would loop back to each point in every other row, to get only the y value for each line, and it would take the values from only the last column of my data (column 716).
needless to say, it did not work as intended, any suggestions?
EDIT:
spreadsheet with just a small portion of values here
and the code used to generate the lines:
for (j in (1:2218)*2) {
x <- unlist(e_web_clear[2*j-1,])
y <- unlist(e_web_clear[2*j,])
lines(x,y,'l',lwd=.00000000001, col="black")
}
data was imported as text file
Edit2:
this is the graph i am getting.
the graph i want to get would have the endpoint of each line highlighted in light blue. i believe it should look something like this. http: / /imgur.com/13b9MZL
figured it out.
I edited my line loop to place a point on the last vector point of each line.
for (j in (1:2218)*2) {
x <- unlist(e_web_clear[2*j-1,])
y <- unlist(e_web_clear[2*j,])
lines(x,y,'l',lwd=.00000000001, col="black")
points(x[358], y[358], lwd = 1.5, cex = .1, col = "lightblue")
}

Resources