R rgl plot value not showing on axis - r

I'm using the rgl package in r to plot some data. As done here:
http://www.r-bloggers.com/creating-3d-geographical-plots-in-r-using-rgl/
For some reason the scale does not align with the graph.
I changed the scale of the X and Z axis to increase the relief, which I initially thought was causing the issue, but in the example below, even if I change 0.02 to 1 the issue occurs.
library(rgl)
rdata <- c(0.8926,0.8986,0.9478,0.9672,0.916,0.912,0.9324,0.9532,0.9488,0.9376,0.921,0.927,0.9728,0.956,0.9318,0.9202)
labs <-c(100,200,500,1000)
rmatrix <- matrix(rdata, nrow=4,ncol=4,)
dimnames(rmatrix) <- list(labs,labs)
y <- as.matrix(rmatrix)
x <- 0.02*(1:nrow(y))
z <- 0.02*(1:ncol(y))
rgl.surface(x, z, y, color="red", back="lines")
axis3d('x--', labels=row.names(rmatrix),color="black")
Why is this happening?
Thanks for your help!
Mat

Without supplying a value to the labels argument in axis3d, I get an axis with six tick marks. Since you supply a vector with only four values to the labels argument, it looks like axis3d recycles those values to cover all the tick marks.
Tell axis3d at what data values you'd like to place the tick marks by supplying a value to the at argument:
axis3d('x--', at = x, labels=row.names(rmatrix),color="black")
p.s. I had to add the following line before rgl.surface() to avoid getting a segfault
rgl.open()

Related

log="y" convert only y-axis label or also y-coordinates of my data?

I'm building a plot in R and I have used the plot() function, with log="y" parameter.
Does that mean that ONLY the y-axis labels will be converted in log scale OR that also the y-coordinates of my data will be converted in log-scale?
Thank you
When using log = "y" it plots the log-transformed y-values with the labels on the original scale -- the opposite of what you seem to suggest.
Compare these three plots:
x <- rnorm(50)
y <- 2*exp(x) + rexp(50)
plot(x, y) # y-scale, y-scale-labels
plot(x, y, log = "y") # log-y-scale, y-scale-labels
plot(x, log(y)) # log-y-scale, log-y-scale labels
Notice that the last two plots only differs in the y-axis labels. Both are still correct as the axis titles are also different.

Binary spark lines with R

I'm looking to plot a set of sparklines in R with just a 0 and 1 state that looks like this:
Does anyone know how I might create something like that ideally with no extra libraries?
I don't know of any simple way to do this, so I'm going to build up this plot from scratch. This would probably be a lot easier to design in illustrator or something like that, but here's one way to do it in R (if you don't want to read the whole step-by-step, I provide my solution wrapped in a reusable function at the bottom of the post).
Step 1: Sparklines
You can use the pch argument of the points function to define the plotting symbol. ASCII symbols are supported, which means you can use the "pipe" symbol for vertical lines. The ASCII code for this symbol is 124, so to use it for our plotting symbol we could do something like:
plot(df, pch=124)
Step 2: labels and numbers
We can put text on the plot by using the text command:
text(x,y,char_vect)
Step 3: Alignment
This is basically just going to take a lot of trial and error to get right, but it'll help if we use values relative to our data.
Here's the sample data I'm working with:
df = data.frame(replicate(4, rbinom(50, 1, .7)))
colnames(df) = c('steps','atewell','code','listenedtoshell')
I'm going to start out by plotting an empty box to use as our canvas. To make my life a little easier, I'm going to set the coordinates of the box relative to values meaningful to my data. The Y positions of the 4 data series will be the same across all plotting elements, so I'm going to store that for convenience.
n=ncol(df)
m=nrow(df)
plot(1:m,
seq(1,n, length.out=m),
# The following arguments suppress plotting values and axis elements
type='n',
xaxt='n',
yaxt='n',
ann=F)
With this box in place, I can start adding elements. For each element, the X values will all be the same, so we can use rep to set that vector, and seq to set the Y vector relative to Y range of our plot (1:n). I'm going to shift the positions by percentages of the X and Y ranges to align my values, and modified the size of the text using the cex parameter. Ultimately, I found that this works out:
ypos = rev(seq(1+.1*n,n*.9, length.out=n))
text(rep(1,n),
ypos,
colnames(df), # These are our labels
pos=4, # This positions the text to the right of the coordinate
cex=2) # Increase the size of the text
I reversed the sequence of Y values because I built my sequence in ascending order, and the values on the Y axis in my plot increase from bottom to top. Reversing the Y values then makes it so the series in my dataframe will print from top to bottom.
I then repeated this process for the second label, shifting the X values over but keeping the Y values the same.
text(rep(.37*m,n), # Shifted towards the middle of the plot
ypos,
colSums(df), # new label
pos=4,
cex=2)
Finally, we shift X over one last time and use points to build the sparklines with the pipe symbol as described earlier. I'm going to do something sort of weird here: I'm actually going to tell points to plot at as many positions as I have data points, but I'm going to use ifelse to determine whether or not to actually plot a pipe symbol or not. This way everything will be properly spaced. When I don't want to plot a line, I'll use a 'space' as my plotting symbol (ascii code 32). I will repeat this procedure looping through all columns in my dataframe
for(i in 1:n){
points(seq(.5*m,m, length.out=m),
rep(ypos[i],m),
pch=ifelse(df[,i], 124, 32), # This determines whether to plot or not
cex=2,
col='gray')
}
So, piecing it all together and wrapping it in a function, we have:
df = data.frame(replicate(4, rbinom(50, 1, .7)))
colnames(df) = c('steps','atewell','code','listenedtoshell')
BinarySparklines = function(df,
L_adj=1,
mid_L_adj=0.37,
mid_R_adj=0.5,
R_adj=1,
bottom_adj=0.1,
top_adj=0.9,
spark_col='gray',
cex1=2,
cex2=2,
cex3=2
){
# 'adJ' parameters are scalar multipliers in [-1,1]. For most purposes, use [0,1].
# The exception is L_adj which is any value in the domain of the plot.
# L_adj < mid_L_adj < mid_R_adj < R_adj
# and
# bottom_adj < top_adj
n=ncol(df)
m=nrow(df)
plot(1:m,
seq(1,n, length.out=m),
# The following arguments suppress plotting values and axis elements
type='n',
xaxt='n',
yaxt='n',
ann=F)
ypos = rev(seq(1+.1*n,n*top_adj, length.out=n))
text(rep(L_adj,n),
ypos,
colnames(df), # These are our labels
pos=4, # This positions the text to the right of the coordinate
cex=cex1) # Increase the size of the text
text(rep(mid_L_adj*m,n), # Shifted towards the middle of the plot
ypos,
colSums(df), # new label
pos=4,
cex=cex2)
for(i in 1:n){
points(seq(mid_R_adj*m, R_adj*m, length.out=m),
rep(ypos[i],m),
pch=ifelse(df[,i], 124, 32), # This determines whether to plot or not
cex=cex3,
col=spark_col)
}
}
BinarySparklines(df)
Which gives us the following result:
Try playing with the alignment parameters and see what happens. For instance, to shrink the side margins, you could try decreasing the L_adj parameter and increasing the R_adj parameter like so:
BinarySparklines(df, L_adj=-1, R_adj=1.02)
It took a bit of trial and error to get the alignment right for the result I provided (which is what I used to inform the default values for BinarySparklines), but I hope I've given you some intuition about how I achieved it and how moving things using percentages of the plotting range made my life easier. In any event, I hope this serves as both a proof of concept and a template for your code. I'm sorry I don't have an easier solution for you, but I think this basically gets the job done.
I did my prototyping in Rstudio so I didn't have to specify the dimensions of my plot, but for posterity I had 832 x 456 with the aspect ratio maintained.

R Polygon Plot Not Shading to X Axis

Using R and polygon I'm trying to shade the area under the line of a plot from the line to the x-axis and I'm not sure what I am doing wrong here.
The shading is using some point in the middle of the y range to shade from, not 0, the x-axis.
The data set ratioresults is a zoo object but I don't think that's the issue since I tried coercing the y values to as.numeric and as.vector and got the same results.
Code:
plot(index(ratioresults),ratioresults$ratio, type="o", col="red")
polygon(c(1,index(ratioresults),11),c(0, ratioresults$ratio, 0) , col='red')
What's index(ratioresults)? For a simple zoo object I see:
> index(x)
[1] "2003-02-01" "2003-02-03" "2003-02-07" "2003-02-09" "2003-02-14"
which is a vector of Date objects. You are trying to prepend/append values of 1 and 11 to this vector. Its not going to work.
Here's a reproducible example:
x=zoo(matrix(runif(11),ncol=1),as.Date("2012-08-01") + 0:10)
colnames(x)="ratio"
plot(index(x),x$ratio,type="o",col="red",ylim=c(0,1))
polygon(index(x)[c(1,1:11,11)],c(0,x$ratio,0),col="red")
Differences from yours:
I call my thing x.
I set ylim on the plot - I don't know how your plot managed to start at 0 on the Y axis.
I complete the polygon using the x-values of the first and 11th (last) point, rather than 1 and 11 themselves.
#With an example dataset: please provide one when you need help!
ratioresults<-as.zoo(runif(10,0,1))
plot(index(ratioresults),ratioresults, type="o", col="red",
xaxs="i",yaxs="i", ylim=c(0,2))
polygon(c(index(ratioresults),rev(index(ratioresults))),
c(as.vector(ratioresults),rep(0,length(ratioresults))),col="red")
The issue with your question is that the x-axis is not a line defined by a given y value by default, so one way to fill under a curve to the x-axis using polygon would be to define a y values for the x-axis using ylim (here I chose 0). Whatever value you choose you will want to specify that the plot stop exactly at the value using yaxs="i".
You also have to construct your polygon with the value you chose for you x-axis.

R 3D plot axis tick labels

I'm plotting a 3D histogram in R using the method from figure 6.15 here.
I've set scale = list(arrow=F), so that I have tick marks instead of arrows on each axis.
The plot looks fine, but I want to change the axis tick labels. My x-axis goes from 1-26, my y from 1-24, and my Z from 0-8E-6. Ideally I'd like a single label at each of the discrete x and y values, and then at some reasonable interval on the z axis.
I've tried using the scale option 'tick.number', but it seems to only take one number, or use the first in a list, so if I set it to 26 I get excess tick marks on the y axis, and the z axis looks like rubbish.
I see there is an 'at' and 'labels' options in scales, much like for 2D plots, but I can't seem to get it to work. The docs indicate it should be a list of vectors with locations and labels for each panel, so I tried:
at = list(c(1:26), c(1:24), c(2*10^-6, 4*10^-6, 8*10^-6))
but it complains:
(list) object cannot be coerces to type 'double'
I presume if I figure out how to use 'at' then 'label' should become clear.
EDIT:
Here is sample code:
library(latticeExtra)
Cg = 1:25
Cr = 1:25
freqs = rnorm(25, .5, .1)
cloud(freqs~Cg*Cr, xlim=c(27,-1), ylim=c(25,-1), panel.3d.cloud=panel.3dbars, par.settings=list(box.3d = list(col="transparent")), col.facet="grey", scales=list(arrows=F))
My data has different lengths X and Y axes, and not just the diagonal is filled, but it shows the axis problem.
From the docs of cloud (lattice):
‘at’ gives the vector of
cutpoints where the colors change
So it needs to be a vector, not a list of vectors. The error you are getting is caused by a failure to transform your list of vectors to numeric:
at = list(c(1:26), c(1:24), c(2*10^-6, 4*10^-6, 8*10^-6))
> as.numeric(at)
Error: (list) object cannot be coerced to type 'double'
The at parameter describes where the colors change, similar to levelplot. So it only needs to be one vector.
Those result needs further work, but it does satisfy your request and shows you what is meant by passing the arguments to 'scales' as a list:
cloud(freqs~Cg*Cr, xlim=c(27,-1), ylim=c(25,-1),zlim=c(0,1), # needed to add zlim
panel.3d.cloud=panel.3dbars, par.settings=list(box.3d = list(col="transparent")),
col.facet="grey",
scales=list(arrows=F, x=list(at = c(1:26), lab=c(1:26)) ,
y=list(at= c(1:24), lab=c(1:24)),
z= list(rot=20, # to prevent over-riding the tick marks
at= c(.2,.4,.8) , # data spans larger range
lab=c("2*10^-6 ", "4*10^-6 ", "8*10^-6 ") )
) )
The range of z is simply not what you offered with those small values, so you need to accept that reality. If you want to relabel the proportions, then I have shown you how to do it.

R: mirror y-axis from a plot

I have this problem. I got a heatmap, (but i suppose this applies to every plot) but I need to mirror my y-axis.
I got here some example code:
library(gstat)
x <- seq(1,50,length=50)
y <- seq(1,50,length=50)
z <- rnorm(1000)
df <- data.frame(x=x,y=y,z=z)
image(df,col=heat.colors(256))
This will generate the following heatmap
But I need the y-axis mirrored. Starting with 0 on the top and 50 on the bottom. Does anybody has a clue as to what I must do to change this?
See the help page for ?plot.default, which specifies
xlim: the x limits (x1, x2) of the plot. Note that ‘x1 > x2’ is
allowed and leads to a ‘reversed axis’.
library(gstat)
x <- seq(1,50,length=50)
y <- seq(1,50,length=50)
z <- rnorm(1000)
df <- data.frame(x=x,y=y,z=z)
So
image(df,col=heat.colors(256), ylim = rev(range(y)))
Does this work for you (it's a bit of a hack, though)?
df2<-df
df2$y<-50-df2$y #reverse oredr
image(df2,col=heat.colors(256),yaxt="n") #avoid y axis
axis(2, at=c(0,10,20,30,40,50), labels=c(50,40,30,20,10,0)) #draw y axis manually
The revaxis function in the plotrix package "reverses the sense of either or both the ‘x’ and ‘y’ axes". It doesn't solve your problem (Nick's solution is the correct one) but can be useful when you need to plot a scatterplot with reversed axes.
I would use rev like so:
df <- data.frame(x=x,y=rev(y),z=z)
In case you were not aware, notice that df is actually a function. You might want to be careful when overwriting. If you rm(df), things will go back to normal.
Don't forget to relabel the y axis as Nick suggests.
For the vertical axis increasing in the downward direction, I provided two ways (two different answers) for the following question:
R - image of a pixel matrix?

Resources