Understanding l_ply from plyr - r

From the documentation:
All output is discarded. This is useful for functions that you are calling purely for their side effects like displaying plots or saving output.
I've spent some time playing around and trying to find a suitable use case but haven't(yet).
Looking at the examples hasn't helped me better understand it.
Sample usage:
l_ply(iris[1:5,1], function(x) print(summary(x)))
This will work.
However, under what circumstances might one need to print and then discard these results?

Consider the following
X <- matrix (c (rnorm (50)), ncol = 5);
Assume each colmn of X indicates a series which you want to overplot.
You can do it as following, by first creating an empty plot and then plotting the series corresponding to each column, using lapply. Although lapply will return the values returned by the plot call that we do not want.
plot (NULL, ylim = range (X), xlim = c (1, nrow (X)));
lapply (1:ncol (X), function (i) points (X[,i], type = "o", col = i));
Instead you can use
plot (NULL, ylim = range (X), xlim = c (1, nrow (X)));
l_ply (1:ncol (X), function (i) points (X[,i], type = "o", col = i));
This has the same effect but does not return the values returned by plot. Here, the "side effect" is the plot function plotting on the device.

Related

Making multiple multi-line plots from one matrix

I'm wondering if there's a way to combine the apply function along with the matplot function to generate a new plot for every n columns in a matrix.
I currently have a matrix with 1350 rows with 640 columns. I'm plotting the values for all the rows for every 8 columns using matplot:
png("cmpd1.png")
matplot(data[,1:8], type="l", y-lab="z-score", axes = F)
axis(side=2)
dev.off()
I want to automate this a bit and have the column values shift by eight each loop and the label on the png to change by one.
Can someone please give directions?
Here is an answer with vapply() and formatted plot names. The closed device id will be returned.
data <- matrix(rnorm(100*128),nrow = 100,ncol = 128)
vapply(seq(from=1,to=ncol(data)-8,by=8),
FUN = function (x) {
png(paste0("cmpd",formatC(width = 3, format = "d", flag="0", x=x%/%8),".png"))
matplot(data[,x:(x+8)], type="l", ylab="z-score", axes = F)
invisible(dev.off())
},
FUN.VALUE=integer(1)
)
I think there is a version with lapply() but a loop does the job as well
for(i in seq(1,ncol(data),8)){
png(paste0("cmpd",i,".png"))
matplot(data[,i:(i+7)], type="l", ylab="z-score", axes = F)
axis(side=2)
dev.off()
}

Plot a frame when encountering empty vectors in R?

Suppose I have three vectors, one empty (here x.y1) and others not empty (here x.y2 and x.y3). My goal is for empty vectors, an empty plot be plotted (just a frame with nothing in it).
Given my plotting plan detailed below, is it possible that before the final plotting by lapply I could have a function that would check if the vector is empty and then lpply just create a frame for plot (e.g., plot.new() ; box()) for the empty vectors to be plotted?
x.y1 = c()
x.y2 = c(2, 3)
x.y3 = c(6, 2)
m = matrix(1:3); layout(m)
plot.names = noquote(paste0("x.y", 1:3))
lapply(plot.names, plot)
# Error: need finite 'ylim' values # Right now I get this error due to the empty vector!
par(mfrow = c(1,3))
lapply(mget(plot.names), function(a)
if(is.null(a)){
plot(0,0, type = "n")
}else{
plot(a)
})

R plot of a matrix of complex numbers

I have a matrix of complex values.
If I issue the command:
plot(myMatrix)
then it shows on the graphics device a kind of scatterplot, with X-axis labeled Re(myMatrix) and Y-axis with Im(myMatrix). This shows the information I'm looking for, as I can see distinct clusters, that I cannot see with only one column.
My questions are :
I assume there is one point per matrix row. Is it right ?
How is calculated Re(myMatrix) for each row vector ?
It is not Re(myMatrix[1,row]), but seems to be a mix of all values of row vector. I would like to be able to get these values, so to know how to compute them with R.
No, there is one point for each matrix element.
set.seed(42)
mat <- matrix(complex(real = rnorm(16), imaginary = rlnorm(16)), 4)
plot(mat)
points(Re(mat[1,1]), Im(mat[1,1]), col = "red", pch = ".", cex = 5)
Look for the red dot:
You'd get the same plot, if you plotted a vector instead of a matrix, i.e., plot(c(mat)).
This happens because plot.default calls xy.coords and that function contains the following code:
else if (is.complex(x)) {
y <- Im(x)
x <- Re(x)
xlab <- paste0("Re(", ylab, ")")
ylab <- paste0("Im(", ylab, ")")
}
else if (is.matrix(x) || is.data.frame(x)) {
This means, that the fact that input is complex takes priority over it being a matrix.

Graphing a polynomial output of calc.poly

I apologize first for bringing what I imagine to be a ridiculously simple problem here, but I have been unable to glean from the help file for package 'polynom' how to solve this problem. For one out of several years, I have two vectors of x (d for day of year) and y (e for an index of egg production) data:
d=c(169,176,183,190,197,204,211,218,225,232,239,246)
e=c(0,0,0.006839425,0.027323127,0.024666883,0.005603878,0.016599262,0.002810977,0.00560387 8,0,0.002810977,0.002810977)
I want to, for each year, use the poly.calc function to create a polynomial function that I can use to interpolate the timing of maximum egg production. I want then to superimpose the function on a plot of the data. To begin, I have no problem with the poly.calc function:
egg1996<-poly.calc(d,e)
egg1996
3216904000 - 173356400*x + 4239900*x^2 - 62124.17*x^3 + 605.9178*x^4 - 4.13053*x^5 +
0.02008226*x^6 - 6.963636e-05*x^7 + 1.687736e-07*x^8
I can then simply
plot(d,e)
But when I try to use the lines function to superimpose the function on the plot, I get confused. The help file states that the output of poly.calc is an object of class polynomial, and so I assume that "egg1996" will be the "x" in:
lines(x, len = 100, xlim = NULL, ylim = NULL, ...)
But I cannot seem to, based on the example listed:
lines (poly.calc( 2:4), lty = 2)
Or based on the arguments:
x an object of class "polynomial".
len size of vector at which evaluations are to be made.
xlim, ylim the range of x and y values with sensible defaults
Come up with a command that successfully graphs the polynomial "egg1996" onto the raw data.
I understand that this question is beneath you folks, but I would be very grateful for a little help. Many thanks.
I don't work with the polynom package, but the resultant data set is on a completely different scale (both X & Y axes) than the first plot() call. If you don't mind having it in two separate panels, this provides both plots for comparison:
library(polynom)
d <- c(169,176,183,190,197,204,211,218,225,232,239,246)
e <- c(0,0,0.006839425,0.027323127,0.024666883,0.005603878,
0.016599262,0.002810977,0.005603878,0,0.002810977,0.002810977)
egg1996 <- poly.calc(d,e)
par(mfrow=c(1,2))
plot(d, e)
plot(egg1996)

How to draw lines on a plot in R?

I need to draw lines from the data stored in a text file.
So far I am able only to draw points on a graph and i would like to have them as lines (line graph).
Here's the code:
pupil_data <- read.table("C:/a1t_left_test.dat", header=T, sep="\t")
max_y <- max(pupil_data$PupilLeft)
plot(NA,NA,xlim=c(0,length(pupil_data$PupilLeft)), ylim=c(2,max_y));
for (i in 1:(length(pupil_data$PupilLeft) - 1))
{
points(i, y = pupil_data$PupilLeft[i], type = "o", col = "red", cex = 0.5, lwd = 2.0)
}
Please help me change this line of code:
points(i, y = pupil_data$PupilLeft[i], type = "o", col = "red")
to draw lines from the data.
Here is the data in the file:
PupilLeft
3.553479
3.539469
3.527239
3.613131
3.649437
3.632779
3.614373
3.605981
3.595985
3.630766
3.590724
3.626535
3.62386
3.619688
3.595711
3.627841
3.623596
3.650569
3.64876
By default, R will plot a single vector as the y coordinates, and use a sequence for the x coordinates. So to make the plot you are after, all you need is:
plot(pupil_data$PupilLeft, type = "o")
You haven't provided any example data, but you can see this with the built-in iris data set:
plot(iris[,1], type = "o")
This does in fact plot the points as lines. If you are actually getting points without lines, you'll need to provide a working example with your data to figure out why.
EDIT:
Your original code doesn't work because of the loop. You are in effect asking R to plot a line connecting a single point to itself each time through the loop. The next time through the loop R doesn't know that there are other points that you want connected; if it did, this would break the intended use of points, which is to add points/lines to an existing plot.
Of course, the line connecting a point to itself doesn't really make sense, and so it isn't plotted (or is plotted too small to see, same result).
Your example is most easily done without a loop:
PupilLeft <- c(3.553479 ,3.539469 ,3.527239 ,3.613131 ,3.649437 ,3.632779 ,3.614373
,3.605981 ,3.595985 ,3.630766 ,3.590724 ,3.626535 ,3.62386 ,3.619688
,3.595711 ,3.627841 ,3.623596 ,3.650569 ,3.64876)
plot(PupilLeft, type = 'o')
If you really do need to use a loop, then the coding becomes more involved. One approach would be to use a closure:
makeaddpoint <- function(firstpoint){
## firstpoint is the y value of the first point in the series
lastpt <- firstpoint
lastptind <- 1
addpoint <- function(nextpt, ...){
pts <- rbind(c(lastptind, lastpt), c(lastptind + 1, nextpt))
points(pts, ... )
lastpt <<- nextpt
lastptind <<- lastptind + 1
}
return(addpoint)
}
myaddpoint <- makeaddpoint(PupilLeft[1])
plot(NA,NA,xlim=c(0,length(PupilLeft)), ylim=c(2,max(PupilLeft)))
for (i in 2:(length(PupilLeft)))
{
myaddpoint(PupilLeft[i], type = "o")
}
You can then wrap the myaddpoint call in the for loop with whatever testing you need to decide whether or not you will actually plot that point. The function returned by makeaddpoint will keep track of the plot indexing for you.
This is normal programming for Lisp-like languages. If you find it confusing you can do this without a closure, but you'll need to handle incrementing the index and storing the previous point value 'manually' in your loop.
There is a strong aversion among experienced R coders to using for-loops when not really needed. This is an example of a loop-less use of a vectorized function named segments that takes 4 vectors as arguments: x0,y0, x1,y1
npups <-length(pupil_data$PupilLeft)
segments(1:(npups-1), pupil_data$PupilLeft[-npups], # the starting points
2:npups, pupil_data$PupilLeft[-1] ) # the ending points

Resources