R: How to have nice intersections between multiple wireframes (lattice) - r

Given the following R code:
require(lattice)
x <- c(1:10)
y <- c(1:10)
g <- expand.grid(x = 1:10, y = 1:10, gr = 1:2)
g$z <- c(as.vector(outer(x,y,"*")), rep(50,100))
wireframe(z ~ x * y, data = g, groups = gr)
The intersection of the resulting surfaces is ugly, since it follows the grid-lines.
Is there a way to make the intersection between the surfaces look nicer (besides increasing the resolution of the grid)? Maybe by passing some parameters or using another package for visualization?

Well, since I couldn't resist goofing off, here are a few possiblities for ways to smooth your data.
The package scvm appears to have some 2D model-fitting tools.
The fields package is recommended here: How can I smooth an array in R?
The DiceKriging package is reviewed here: https://stats.stackexchange.com/questions/13510/fitting-multivariate-natural-cubic-spline

Related

Having trouble with paths returned by flowPath in raster R-package

Paths returned by the flowPath function in the raster package consist of segments parallel to the x- and y-axes.
Starting with the Vector Field Plots example in the rasterVis documentation (https://oscarperpinan.github.io/rastervis/), I try to find the flow-path from a starting point on the surface, but the path output is incorrect.
library(raster)
library(rasterVis)
proj <- CRS('+proj=longlat +datum=WGS84')
df <- expand.grid(x = seq(-2, 2, .01), y = seq(-2, 2, .01))
df$z <- with(df, (3*x^2 + y)*exp(-x^2-y^2))
r <- rasterFromXYZ(df, crs=proj)
# Up to this point we follow the example in the rasterVis documentation
# Now attempt to find the path from a point on the surface
contour(r$z)
r.fd<-terrain(r,opt='flowdir')
r.c<-cellFromXY(r,cbind(-1,0))
r.p<-flowPath(r.fd,r.c)
p.xy<-xyFromCell(r.fd,r.p)
lines(p.xy,col='green')
Flow path from point (-1,0) depicting undesired behavior.
As you can see above, the flow path proceeds to the minimum at approximately (0,-.8) by moving towards +x and then -y. I have been unable to construct a data set which does not exhibit this problem. However: the example included in the flowPath documentation (in the raster package, using the volcano data) produces output one might expect and does not exhibit this problem.
What am I doing incorrectly that I cannot extend the example in the rasterVis documentation?
Addendum: My reason for questioning the output may be more a misunderstanding of what flowPath is supposed to return. I expected the kind of path a droplet might follow as it moves downhill. Like this:
Expected flowPath
This was computed using a simple steepest-descent walk. However, if (as stated by respondent Hijmans) flowPath is working as intended, then I may need to find another function which provides the path droplets would follow moving downhill.
Why is the path incorrect? It looks good to me. Illustrated by aggregating and labeling.
library(raster)
proj <- CRS('+proj=longlat +datum=WGS84')
df <- expand.grid(x = seq(-2, 2, .01), y = seq(-2, 2, .01))
df$z <- with(df, (3*x^2 + y)*exp(-x^2-y^2))
r <- rasterFromXYZ(df, crs=proj)
r <- aggregate(r, 25) * 10
r.fd <- terrain(r, opt='flowdir')
r.p <- flowPath(r.fd, cbind(-1,0))
p.xy <- xyFromCell(r.fd,r.p)
plot(r)
lines(p.xy,col='green', lwd=2)
text(r)
Add some noise to get a more wiggly path
set.seed(01234)
r <- rasterFromXYZ(df, crs=proj)
r <- aggregate(r, 10) * 10
r <- r + runif(ncell(r), 1, 2)
r.fd <- terrain(r, opt='flowdir')
r.p <- flowPath(r.fd, cbind(-1,0))
p.xy <- xyFromCell(r.fd,r.p)
plot(r)
lines(p.xy,col='green', lwd=2)

Can I re-scale the x/y axis aspect ratio in R with rayshader?

I have some data from lab equipment that can be represented as a matrix by a contour plot/heatmap.
I would like to try illustrating this data in R with the rayshader package.
My problem is that the data is far from square in shape, the matrix is 33 rows by 48003 columns. When I plot this with rayshader I get a thin line:
library(dplyr)
library(rayshader)
set.seed(1742)
df <- matrix(rnorm(10000), nrow = 10)
rownames(df) <- 1:10
colnames(df) <- seq(0.01, 10, 0.01)
df %>%
sphere_shade(texture = "desert") %>%
plot_map()
Is there a way to make rayshader plot this as a square by manipulating the x/y aspect ratios? Or to plot them on an equivalent scale (one dimension collects data much faster than the other)? I can't find anything in the docs.
In this example, I tried naming the rows and columns so they were both collected over 10 minutes, but it didn't change the result.
The end result should look similar to:
library(plotly)
set.seed(1742)
plot_ly(z = ~matrix(rnorm(10000), nrow = 10)) %>%
add_surface()
Many thanks.
Solution for rayshader::plot_3d() is to use scale = c(x, y, z), which will alter the x/y/z aspect ratios. This was hidden, but didn't take that much sluthing to find the answer. It is a setting in rgl::par3d(), which is called by plot_3d().
However, I couldn't get plot_map() to work. When I tried adding the argument asp = 1, which is used by rgl::par3d(), it threw errors.

How to increase the size of the text in a Bayesian network plot with bnlearn in R

I am trying to draw a Bsyesian Network in R with bnlearn. Here is the my R code
library(bnlearn)
library(Rgraphviz)
first_variable <- rnorm(100)
second_variable <- rnorm(100)
third_variable <- rnorm(100)
v <- data.frame(first_variable,second_variable,third_variable)
b <- hc(v)
hlight <- list(nodes = nodes(b), arcs = arcs(b),col = "grey", textCol = "red")
pp <- graphviz.plot(b, highlight = hlight)
The code above works, but the size of the text in the plot is very smaller than I expected. Here it is:
I think that is because my variables have long names . In my real data, the variable names are even longer. Here is the BN plot for my real dataset:
Is there any way to increase the size of the text in the plot?
This is basically answered in the post here (albeit that wasn't the OPs only question).
The two approaches suggested are to change the text size globally:
par(cex=0.05)
graphviz.plot(res, highlight =
list(nodes=nodes(res), fill="lightgreen", col="black"))
But I don't find that this works.
Alternatively (and this is what I have been doing) is to change the node characteristics separately:
g <- Rgraphviz::layoutGraph(bnlearn::as.graphNEL(b))
graph::nodeRenderInfo(g) <- list(fontsize=20)
Rgraphviz::renderGraph(g)

plot raster with discrete colors using rasterVis

I have a few rasters I would like to plot using gplot in the rasterVis package. I just discovered gplot (which is fantastic and so much faster than doing data.frame(rasterToPoints(r))). However, I can't get a discrete image to show. Normally if r is a raster, I'd do:
rdf=data.frame(rasterToPoints(r))
rdf$cuts=cut(rdf$value,breaks=seq(0,max(rdf$value),length.out=5))
ggplot(rdf)+geom_raster(aes(x,y,fill=cuts))
But is there a way to avoid the call to rasterToPoints? It is very slow with large rasters. I did find I could do:
cuts=cut_interval(r#data#values,n=5)
but if you set the fill to cuts it plots the integer representation of the factors.
Here is some reproducible data:
x=seq(-107,-106,.1)
y=seq(33,34,.1)
coords=expand.grid(x,y)
rdf=data.frame(coords,depth=runif(nrow(coords),0,2)))
names(rdf)=c('x','y','value')
r=rasterFromXYZ(rdf)
Thanks
gplot is a very simple wrapper around ggplot so don't expect too
much from it. Instead, you can use part of its code to build your own
solution. The main point here is to use sampleRegular to reduce the
number of points to be displayed.
library(raster)
library(ggplot2)
x <- sampleRegular(r, size=5000, asRaster = TRUE)
dat <- as.data.frame(r, xy=TRUE)
dat$cuts <- cut(dat$value,
breaks=seq(0, max(dat$value), length.out=5))
ggplot(aes(x = x, y = y), data = dat) +
geom_raster(aes(x, y, fill=cuts))
However, if you are open to plot without ggplot2 you may find useful
this other
answer.

contour plot of a custom function in R

I'm working with some custom functions and I need to draw contours for them based on multiple values for the parameters.
Here is an example function:
I need to draw such a contour plot:
Any idea?
Thanks.
First you construct a function, fourvar that takes those four parameters as arguments. In this case you could have done it with 3 variables one of which was lambda_2 over lambda_1. Alpha1 is fixed at 2 so alpha_1/alpha_2 will vary over 0-10.
fourvar <- function(a1,a2,l1,l2){
a1* integrate( function(x) {(1-x)^(a1-1)*(1-x^(l2/l1) )^a2} , 0 , 1)$value }
The trick is to realize that the integrate function returns a list and you only want the 'value' part of that list so it can be Vectorize()-ed.
Second you construct a matrix using that function:
mat <- outer( seq(.01, 10, length=100),
seq(.01, 10, length=100),
Vectorize( function(x,y) fourvar(a1=2, x/2, l1=2, l2=y/2) ) )
Then the task of creating the plot with labels in those positions can only be done easily with lattice::contourplot. After doing a reasonable amount of searching it does appear that the solution to geom_contour labeling is still a work in progress in ggplot2. The only labeling strategy I found is in an external package. However, the 'directlabels' package's function directlabel does not seem to have sufficient control to spread the labels out correctly in this case. In other examples that I have seen, it does spread the labels around the plot area. I suppose I could look at the code, but since it depends on the 'proto'-package, it will probably be weirdly encapsulated so I haven't looked.
require(reshape2)
mmat <- melt(mat)
str(mmat) # to see the names in the melted matrix
g <- ggplot(mmat, aes(x=Var1, y=Var2, z=value) )
g <- g+stat_contour(aes(col = ..level..), breaks=seq(.1, .9, .1) )
g <- g + scale_colour_continuous(low = "#000000", high = "#000000") # make black
install.packages("directlabels", repos="http://r-forge.r-project.org", type="source")
require(directlabels)
direct.label(g)
Note that these are the index positions from the matrix rather than the ratios of parameters, but that should be pretty easy to fix.
This, on the other hand, is how easilyy one can construct it in lattice (and I think it looks "cleaner":
require(lattice)
contourplot(mat, at=seq(.1,.9,.1))
As I think the question is still relevant, there have been some developments in the contour plot labeling in the metR package. Adding to the previous example will give you nice contour labeling also with ggplot2
require(metR)
g + geom_text_contour(rotate = TRUE, nudge_x = 3, nudge_y = 5)

Resources