Are there restrictions when doing R plots in Sage? - r

I have done some data analysis with Sage and R, and at this point I would like to produce a nice set of plots to condense the results so that I can present them properly.
What I've done is set the entire notebook to R, in the drop-down menu. Then I execute some code in a number of cells. Works great. The largest cell with code I have fills up most of my screen (five large SQL-selects to pull data from a database and store in variables). So for some code it seems like there are no restrictions at all.
Now I'm doing the plottings. And I start that off with these two lines to get a canvas:
png("temp.png", width=1800, height=1000)
par(mfrow=c(2,2))
Then I want to get four plots within the same PNG, so that it is nicely compressed together. But Sage just refuses to show any plot results with all four plots. Just having the first two plots works great (I get two blank spaces at the bottom). Both the two first plots work great, or the two middle plots, or the two last, or the first and the last. But three plots doesn't work and neither does four.
So I tried something a lot more simple, like this:
png("temp.png", width=1800, height=1000)
par(mfrow=c(2,2))
plot(1:20)
plot(20:1)
plot(seq(5,15,0.5))
plot(seq(15,5,-0.5))
dev.off()
This code works great, and I get four simple plots. And I can even extend that to look more like what I am actually trying to plot like this and make it work:
png("temp.png", width=1800, height=1000)
par(mfrow=c(2,2))
plot(1:20)
lines(c(0,500),c(0,0), lwd=1, col="Black", xlab="", ylab="")
par(new=T)
plot(data.frame(seq(0,20), seq(0,20)), type="l", lwd=2, col="Red", axes=F, xlab="", ylab="")
plot(20:1)
lines(c(0,500),c(0,0), lwd=1, col="Black", xlab="", ylab="")
par(new=T)
plot(data.frame(seq(0,20), seq(0,20)), type="l", lwd=2, col="Red", axes=F, xlab="", ylab="")
plot(seq(5,15,0.5))
lines(c(0,500),c(0,0), lwd=1, col="Black", xlab="", ylab="")
par(new=T)
plot(data.frame(seq(0,20), seq(0,20)), type="l", lwd=2, col="Red", axes=F, xlab="", ylab="")
plot(seq(15,5,-0.5))
lines(c(0,500),c(0,0), lwd=1, col="Black", xlab="", ylab="")
par(new=T)
plot(data.frame(seq(0,20), seq(0,20)), type="l", lwd=2, col="Red", axes=F, xlab="", ylab="")
dev.off()
So far so good. Seems to me like my idea about how I want to show my data should work. But my actual code doesn't work. Here's what it looks like in my actual plotting cell (that shows nothing):
png("temp.png", width=1800, height=1000)
par(mfrow=c(2,2))
smoothScatter(WFr, colramp=colorRampPalette(c("white", "black")), xlab="Julian day", ylab="Residual", xlim=c(175,279), ylim=c(-0.3,0.3), main="Wild Females, model residuals over time")
lines(c(0,500),c(0,0), lwd=1, col="Black", xlab="", ylab="", xlim=c(175,279), ylim=c(-0.3,0.3))
par(new=T)
plot(data.frame(seq(100,299), WFrlm$coef[1]+WFrlm$coef[2]*seq(100,299)), type="l", lwd=2, col="Red", axes=F, xlab="", ylab="", xlim=c(175,279), ylim=c(-0.3,0.3))
smoothScatter(WMr, colramp=colorRampPalette(c("white", "black")), xlab="Julian day", ylab="Residual", xlim=c(175,279), ylim=c(-0.3,0.3), main="Wild Males, model residuals over time")
lines(c(0,500),c(0,0), lwd=1, col="Black", xlab="", ylab="", xlim=c(175,279), ylim=c(-0.3,0.3))
par(new=T)
plot(data.frame(seq(100,299), WMrlm$coef[1]+WMrlm$coef[2]*seq(100,299)), type="l", lwd=2, col="Red", axes=F, xlab="", ylab="", xlim=c(175,279), ylim=c(-0.3,0.3))
smoothScatter(CFr, colramp=colorRampPalette(c("white", "black")), xlab="Julian day", ylab="Residual", xlim=c(175,279), ylim=c(-0.3,0.3), main="Cultured Females, model residuals over time")
lines(c(0,500),c(0,0), lwd=1, col="Black", xlab="", ylab="", xlim=c(175,279), ylim=c(-0.3,0.3))
par(new=T)
plot(data.frame(seq(100,299), CFrlm$coef[1]+CFrlm$coef[2]*seq(100,299)), type="l", lwd=2, col="Red", axes=F, xlab="", ylab="", xlim=c(175,279), ylim=c(-0.3,0.3))
smoothScatter(CMr, colramp=colorRampPalette(c("white", "black")), xlab="Julian day", ylab="Residual", xlim=c(175,279), ylim=c(-0.3,0.3), main="Cultured Males, model residuals over time")
lines(c(0,500),c(0,0), lwd=1, col="Black", xlab="", ylab="", xlim=c(175,279), ylim=c(-0.3,0.3))
par(new=T)
plot(data.frame(seq(100,299), CMrlm$coef[1]+CMrlm$coef[2]*seq(100,299)), type="l", lwd=2, col="Red", axes=F, xlab="", ylab="", xlim=c(175,279), ylim=c(-0.3,0.3))
dev.off()
What is wrong here? Since each of the plots seem to work fine on its own, and they do print out when I put them in pairs, why won't they show up when I try it with all four? BTW, I have also tried with plot() instead of smoothScatter() and it is the same thing; shows 2 plots but not more. I also tried par(mfrow=c(4,1)) but no difference.
At first I thought there was a limit as to how much R code you can put in one single cell, but my SQL-select-cells have much more code than the plotting cells. So I'm wondering if maybe there is some sort of time-out that makes Sage stop waiting for the PNG output? I tried searching my hard drive for "temp.png" too but I don't get anything showing up.
Is there a restriction on how much data you can pass to a plot in Sage? Can I adjust this somehow? Or is there some sort of debug mode I can enter to better understand why nothing is happening when I add all four plots to the output?

Short version of my answer there, for completeness:
If you have your own installation, then in devel/sage/sage/interfaces/r.py, replace
eval_using_file_cutoff=1024)
with the cutoff you would like in terms of the number of characters. (You'll have to do ./sage -b before restarting the server.) If you don't, you won't be able to address this directly using the drop-down menu, though using r.eval() in the normal Sage menu with some extra options should do it.

There is no need to change any r.py code, as kcrisman suggested in his answer. The R code always runs, but when the code is longer than 1024 characters R code is run as a script file instead of as a command line, and then Sage fails to detect any output that is generated.
The workaround that I found is to save output from long code snippets into a known file, e.g. "~/temp.png" for plots. Then you can use the next cell to draw a dummy plot, and then write your previously created plot onto the canvas. Since this plot is generated from a shorter code (less than 1024 characters), Sage will be able to detect the output that is generated the second time around. Here is the code I used:
png("~/output.png", width=1800, height=1000)
par(mfrow=c(2,2))
# do fancy plot stuff here
dev.off()
# <---- I used a second cell here ---->
library(png)
x <- readPNG("~/output.png")
png("tmp.png", width=1800, height=1000)
plot(1:2, type="n", axes=F, xlab="", ylab="")
# rasterImage() prints on the plot. The plot goes from x = c(1,2) to y = c(1,2).
# So we tell rasterImage() to print within that x/y (i.e. "1,1,2,2") to keep
# the plot scaled correctly.
rasterImage(x, 1, 1, 2, 2)
dev.off()
You could of course do it like a function or something. But since it only applies on rare occasions when plot arguments are so long that the code length exceeds 1024 characters, I have only done it as a special cell on its own.

Related

Why do I loose parts of the plot when exporting it as metafile?

I'm working with GLMs and therefore do some plots with the "visreg" package, and I also add usual plots to them. My script looks like this:
library(visreg)
visreg(model01, scale = "response", type="conditional",line=list(col="green"), ylim=c(0,1), xlim=c(0,400), rug=F, axes=F, ann=F)
par(new=T)
plot(data$x ~ data$y, ylim=c(0,1), xlim=c(0,400), col=rgb(0,100,50,50, maxColorValue=255), pch=19, cex=2, axes=F, ann=F)
par(new=T)
visreg(model02, scale = "response", type="conditional",line=list(col="red"), ylim=c(0,1), xlim=c(0,400), rug=F, axes=F, ann=F )
par(new=T)
plot(data$x ~ data$z, ylim=c(0,1), xlim=c(0,400), col=rgb(0,50,100,50, maxColorValue=255), pch=19, cex=2, las=1, xlab="label01", ylab="label02")
axis(1)
axis(2, las=1)
box()
col1 <- c(rgb(0,100,50, maxColorValue=155), rgb(0,50,100, maxColorValue=155))
legend (315, 1.05, legend=c("bla01", "bla02"), col=c("green","red"), y.intersp=1.3, cex=0.9, lty=1, lwd=2, bty="n")
legend (309, 1.06, legend=c("",""), col=col1, pch=19, y.intersp=1.2, bty="n")
The visreg() parts plot the regression model while the plot() parts plot the corresponding data. The whole plot looks the way I want it in RStudio, but when I export it as a metafile I loose the plot() parts of it (except the axis labels, they are still there). Does anybody know why that is and what I can do to export it all as a metafile?
Cheers,
Alex

Thickness of lines, position of box in plot

I am creating a plot with the code below, yet I want to change the following three things and did not succeed so far:
Obviously, the box is misplaced, how can I place the box such that it is not overlapphing with the plots lines?
How can I make the lines (the blue and golden of the plot) thicker? Whatever I tried had no effect
Where can I change the size of the font (axis label, as well as the descriptions in the box and the main label). I know that this is done with par, but not aware where exactly
Thanks
blocked <- c(199.80248, 76.67856, 71.21770)
random <- c(193.31283, 99.37955, 104.22490)
g_range <- range(0, blocked, random)
plot(blocked, type="o", col="lightblue", ylim=g_range,
axes=FALSE, ann=FALSE)
axis(1, at=1:3, lab=c("Pretest","Posttest", "Retention"))
axis(2, las=1, at=40*0:g_range[2])
box()
lines(random, type="o", pch=22, lty=2, col="gold")
title(main="Radialer Fehler der geblockten und variablen Gruppen", col.main="black", font.main=2)
title(xlab="Test", col="black")
title(ylab="radialer Fehler (mm)", col="black")
legend(1.1, g_range[2], c("geblockt","variabel"), cex=0.7,
col=c("lightblue","gold"), pch=2:3, lty=2:3);
You can modify graphical parameters either golbally with par or at each call to a plot function, ie plot, lines...
To get a list of all graphical parameters, you can simply type par().
Concerning your problem, you can make the lines thicker with graphical parameter lwd, either typing first par(lwd = 1.5) (or lower/greater, play with it to see the result) or at each call :
plot(blocked, type="o", col="lightblue", ylim=g_range, axes=FALSE, ann=FALSE, lwd = 1.5)
lines(random, type="o", pch=22, lty=2, col="gold", lwd = 1.5)
Graphical parameter for the size of the font is cex. You can also change the place of the legend using the parameter topright,topleftetc. :
legend("topleft",...)

plot multiple xts objects superimposed with different scales using both vertical axes

I have two univariate time series that would like to plot in the same screen chart. The problem is that they have very different scales and therefore the chart becomes very difficult to interpret. How can I plot each series superimposed but each of them using a different vertical axis?
library(xts)
mytime <- as.POSIXlt(seq(Sys.time()-100*60+1,Sys.time(),by=60), origin= '1970-01-01')
x <- xts(rnorm(1:100),mytime)
y <- xts(rnorm(1:100,100,10),mytime)
plot(as.zoo( merge(x,y)), screens=1)
I'm not so sure this is what you want, but here's an idea:
plot(as.zoo(x), las=1)
par(new=TRUE)
plot(as.zoo(y),
col=2,
bty='n',
xaxt="n",
yaxt="n",
xlab="", ylab="")
axis(4, las=1)
legend("topleft",
legend=c("x","y"),
col=1:2,
lty=1,
cex=0.85)

How to reduce the marker symbol in a line plotted by using R?

I am using R to plot line chart, with the following command
data <- read.table("input_data.txt", header=T, sep="\t")
ind=seq(1,nrow(data),by=2)
pdf(file="result.pdf")
plot_colors <- c("black","red","green","blue","purple","red")
plot(data$column_one, type="l", lty=1, col=plot_colors[1], ann=FALSE)
lines(data$column_two, type="l", lty=2, col=plot_colors[2])
lines(data$column_three, type="o", pch=1, lty=0, col=plot_colors[3], cex=1)
lines(data$column_four, type="o", pch=3, lty=0, col=plot_colors[4], cex=1)
lines(data$column_five, type="o", pch=2, lty=0, col=plot_colors[5], cex=1)
lines(data$column_six, type="o", pch=4, lty=1, col=plot_colors[6], cex=1)
box()
dev.off()
The problem is, I have 500 data points, and the symbol markers are all mashed up on the line, tightly compact on the line. I could not see the symbols on the line.
Is there a way to just show the symbol markers at fixed interval, without them cluttering together?
Use something like that:
lines(data$column_three, type="o", pch=c(1,NA,NA,NA,NA), lty=0, col=plot_colors[3], cex=1)
For the pch command: The number (here "1") defines your symbol as before. The "NA" means, that these points are plotted with no symbol. This vector will be repeatedly used until the end of your plot. Here, every 5th point is plotted with symbol 1.

R, plot , font size changes in multiple plot figures

I am creating graphs for a publication and would like them to have the same font size.
When I create a figure with multiple plots, the font size decreases even though I haven't changed the tiff() resolution or pointsize parameter.
I increased the figure size according to ultimately fit the number of plots, and made sure the margins are equivalent for single and multiple plot figures.
Following is an example code (The font size is consistent between 1x1 and 2x1 figure, but decreases for 3x2 figure):
tiff("1x1.tif", width=3,height=2.5,units="in",res=600,pointsize=8,
compression="lzw",restoreConsole=T)
par(mfrow=c(1,1),mar=c(4,4,.5,.5)+0.1)
plot(x=rnorm(10),y=rnorm(10))
dev.off()
tiff("2x1.tif", height=2.5*2,width=3,units="in",res=600,pointsize=8,
compression="lzw",restoreConsole=T)
par(mfrow=c(2,1),mar=c(2,4,2.5,0.5)+0.1)
plot(x=rnorm(10),y=rnorm(10),xaxt="n",xlab="")
par(mar=c(4,4,0.5,0.5)+0.1)
plot(x=rnorm(10),y=rnorm(10))
dev.off()
tiff("3x2.tif", height=2.5*3,width=3*2,units="in",res=600,pointsize=8,
compression="lzw",restoreConsole=T)
par(mfrow=c(3,2),mar=c(.5,4,4,0.5)+0.1)
plot(x=rnorm(10),y=rnorm(10),xaxt="n",xlab="")
par(mar=c(.5,2,4,2.5)+0.1)
plot(x=rnorm(10),y=rnorm(10),xaxt="n",xlab="",yaxt="n",ylab="")
par(mar=c(2.5,4,2,0.5)+0.1)
plot(x=rnorm(10),y=rnorm(10),xaxt="n",xlab="")
par(mar=c(2.5,2,2,2.5)+0.1)
plot(x=rnorm(10),y=rnorm(10),xaxt="n",xlab="",yaxt="n",ylab="")
par(mar=c(4.5,4,0,0.5)+0.1)
plot(x=rnorm(10),y=rnorm(10))
par(mar=c(4.5,2,0,2.5)+0.1)
plot(x=rnorm(10),y=rnorm(10),yaxt="n",ylab="")
dev.off()
Why is this happening?
P.S.: I'm not using ggplot2 or lattice because I'm using my own error bar function on the "actual" figures (I can't remember why right now but I tried working with the ggplot2 error bars and didn't get what I wanted).
The parameter controlling the overall relative size of objects in the plot (including text) is called cex. When you use many panels it is decreased by default, but it can be overridden by manually setting it to 1.
par(mfrow=c(3,2), mar=c(.5,4,4,0.5)+0.1, cex=1)
Off-topic-tip
It looks like you should use oma (outer margin) rather than calling par(mar=...) between the calls to plot. I find it very useful, but hardly anyone seems to know of it. Also ann=FALSE turns off all anotations, las=1 turns axis tick labels horizontal.
par(mfrow=c(3,2), oma=c(4.5, 4, 4, 2.5), mar=rep(.1, 4), cex=1, las=1)
plot(x=rnorm(10), y=rnorm(10), ann=FALSE, xaxt="n")
plot(x=rnorm(10), y=rnorm(10), ann=FALSE, xaxt="n", yaxt="n")
plot(x=rnorm(10), y=rnorm(10), ann=FALSE, xaxt="n")
plot(x=rnorm(10), y=rnorm(10), ann=FALSE, xaxt="n", yaxt="n")
plot(x=rnorm(10), y=rnorm(10), ann=FALSE)
plot(x=rnorm(10), y=rnorm(10), ann=FALSE, yaxt="n")
title("My plot", outer=TRUE)
mtext("X-axis label", 1, 3, outer=TRUE)
mtext("Y-axis label", 2, 3, outer=TRUE, las=0)

Resources