Plot a frame when encountering empty vectors in R? - 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)
})

Related

Way to progressively overlap line plots in R

I have a for loop from which I call a function grapher() which extracts certain columns from a dataframe (position and w, both continuous variables) and plots them. My code changes the Y variable (called w here) each time it runs and so I'd like to plot it as an overlay progressively. If I run the grapher() function 4 times for example, I'd like to have 4 plots where the first plot has only 1 line, and the 4th has all 4 overlain on each other (as different colours).
I've already tried points() as suggested in other posts, but for some reason it only generates a new graph.
grapher <- function(){
position.2L <- data[data$V1=='2L', 'V2']
w.2L <- data[data$V1=='2L', 'w']
plot(position.2L, w.2L)
points(position.2L, w.2L, col='green')
}
# example of my for loop #
for (t in 1:200){
#code here changes the 'w' variable each iteration of 't'
if (t%%50==0){
grapher()
}
}
Not knowing any details about your situation I can only assume something like this might be applicable.
# Example data set
d <- data.frame(V1=rep(1:2, each=6), V2=rep(1:6, 2), w=rep(1:6, each=2))
# Prepare the matrix we will write to.
n <- 200
m <- matrix(d$w, nrow(d), n)
# Loop progressively adding more noise to the data
set.seed(1)
for (i in 2:n) {
m[,i] <- m[,i-1] + rnorm(nrow(d), 0, 0.05)
}
# We can now plot the matrix, selecting the relevant rows and columns
matplot(m[d$V1 == 1, seq(1, n, by=50)], type="o", pch=16, lty=1)

How to fix ‘Error in FUN(X[[i]], ...) : only defined on a data frame with all numeric variables”

I intend to draw a qq plot on the data, but it reminds me that qqnorm function only works on numerical data.
As the factor include A,B,C,D and their two, three and four way interaction, I have no idea how to convert it into numerical form.
The data is as follows:
Effects,Value
A,76.95
B,-67.52
C,-7.84
D,-18.73
AB,-51.32
AC,11.69
AD,9.78
BC,20.78
BD,14.74
CD,1.27
ABC,-2.82
ABD,-6.5
ACD,10.2
BCD,-7.98
ABCD,-6.25
My code is as follows:
library(readr)
data621 <- read_csv("Desktop/data621.csv")
data621_qq<-qqnorm(data621,xlab = "effects",datax = T)
qqline(data621,probs=c(0.3,0.7),datax = T)
text(data621_qq$x,data621_qq$y,names(data621),pos=4)
Your code would work if using the proper columns instead of the entire data frame. For example,
data621_qq <- qqnorm(data621$Value, xlab = "Effects", datax = TRUE)
qqline(data621$Value, probs = c(0.3, 0.7), datax = TRUE)
text(data621_qq$x, data621_qq$y, data621$Effects, pos=4)
By the way, names(data621) would give you the column names, instead of the effect names (which are stored as values in a column).

Understanding l_ply from plyr

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.

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()
}

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.

Resources