How can I highlight minimum values in a levelplot in R? - r

How can I highlight the ten minimum value grid points of a 385*373 levelplot as black points?
I have the indexes as well as the coordinates of the ten minimum grid points. Preferably I would use the idexes...
I have the following levelplot displaying Europe's air temperature (Z), with X and Y being longitude and latitude respectively.
levelplot(Z ~ X*Y, data=data , xlab="X" , col.regions = heat.colors(100))
One further question: how can I add the country contours with the same projection type as the base data? I tried that before within another function
image(x,y,data,...)
data(wrdl_simpl)
plot(wrld_simpl, add = TRUE)
where the country contours plot seemed to have a totally different projection. However, I want to do this for levelplot() now.
I am very thankful for any help!

lattice plots differ to base plots. Therefore using points does not work. But there are replacement functions. Here is a way to do it:
x <- seq(-10, 10, length.out = 100)
y <- seq(-10, 10, length.out = 100)
z <- as.vector(sqrt(outer(x^2, y^2, "+")))
grid <- cbind(expand.grid(x=x, y=y), z)
minimum <- grid[which.min(grid$z),]
levelplot(z ~ x * y, grid, panel = function(...) {
panel.levelplot(...)
panel.points(x = minimum$x, y = minimum$y, pch = "x", cex =2)
})
We are basically building up the plot inside the panel argument.

Related

How to plot a surface in rgl plot3d

So I have this code that produces the exact surface
f = function(x, y){
z = ((x^2)+(3*y^2))*exp(-(x^2)-(y^2))
}
plot3d(f, col = colorRampPalette(c("blue", "white")),
xlab = "X", ylab = "Y", zlab = "Z",
xlim = c(-3, 3), ylim = c(-3, 3),
aspect = c(1, 1, 0.5))
Giving the following plot:
Now I have some code that does a random walk metropolis algorithm to reproduce the above image. I think it works as if I do another plot of these calculated values I get the next image with 500 points. Here is the code
open3d()
plot3d(x0, y0, f(x0, y0), type = "p")
Which gives the following plot:
I know it's hard looking at this still image but being able to rotate the sampling is working.
Now here is my question: How can I use plot3d() so that I can have a surface that connects all these points and gives a more jagged representation of the exact plot? Or how can I have each point in the z axis as a bar from the xy plane? I just want something more 3 dimensional than points and I can't find how to do this.
Thanks for your help
You can do this by triangulating the surface. You don't give us your actual data, but I can create some similar data using
f = function(x, y){
z = ((x^2)+(3*y^2))*exp(-(x^2)-(y^2))
}
x <- runif(500, -3, 3)
y <- runif(500, -3, 3)
z <- f(x, y)
Then the plotting is done using the method in ?persp3d.deldir:
library(deldir)
library(rgl)
col <- colorRampPalette(c("blue", "white"))(20)[1 + round(19*(z - min(z))/diff(range(z)))]
dxyz <- deldir::deldir(x, y, z = z, suppressMsge = TRUE)
persp3d(dxyz, col = col, front = "lines", back = "lines")
This might need some cosmetic fixes, e.g.
aspect3d(2, 2, 1)
After some rotation, this gives me the following plot:
I'm not sure to understand what you want. If my understanding is correct, here is a solution. Define a parametric representation of your surface:
fx <- function(u,v) u
fy <- function(u,v) v
fz <- function(u,v){
((u^2)+(3*v^2))*exp(-(u^2)-(v^2))
}
Let's say you have these points:
x0 <- seq(-3, 3, length.out = 20)
y0 <- seq(-3, 3, length.out = 20)
Then you can use the function parametric3d of the misc3d package, with the option fill=FALSE to get a wireframe:
library(misc3d)
parametric3d(fx, fy, fz, u=x0, v=y0,
color="blue", fill = FALSE)
Is it what you want?
To get some vertical bars, use the function segments3d of rgl:
i <- 8
bar <- rbind(c(x0[i],y0[i],0),c(x0[i],y0[i],f(x0[i],y0[i])))
segments3d(bar, color="red")
Here is a plot with only 50 points using my original code.
When I then apply what was said by Stéphane Laurent I then get this plot which feels too accurate when given the actual points I have
Perhaps you need to explain to me what is actually happening in the function parametric3d

plot3d() - How to change z axis surface color to heat map color

In the above image the surface colored in z axis (like heat map). I am using plot3d()
plot3d(data$x, data$y, data$z, name = 'Plotly3D graph', type = 'l', axes=F)
I have to repeat the same color as of in the image. By using above code I can get the 3D square but I dont know where to set the color of z axis as same as the image. Please help me in plot3D. If full code is needed will post if required.
Here is sample code:
data1 <- read.csv(file.choose(),1)
# retrieve age column from csv file
var1 <- data1$age
z1 <- rep(1, times=length(var1))
plot3d(var1, length(var1), z1, type="l", xaxt='n', yaxt='n', xlab="Jitter in
ns", ylab="Counts", size=0.05,expand=0.75, col=color[zcol],
ticktype="detailed", zlab="")
Here's one version, using a function from one of the answers to How do I generate a mapping from numbers to colors in R?.
# A function based on Dave X's answer to the colour mapping question
map2color <- function(x, pal, limits = range(x)){
pal[findInterval(x, seq(limits[1], limits[2], length.out = length(pal) + 1),
all.inside=TRUE)]
}
persp3d(volcano, col = map2color(volcano, rainbow(100)))
This produces this image:
To produce solid edges ("curtains" in plot3D), just surround the data with extra rows and columns of its minimum value. For example,
m <- min(volcano)
volcano2 <- cbind(m, rbind(m, volcano, m), m)
To make the edges look flat, you need to add x and y values, just a tiny bit outside the original ones:
x <- c(0.9999, 1:nrow(volcano), nrow(volcano) + 0.0001)
y <- c(0.9999, 1:ncol(volcano), ncol(volcano) + 0.0001)
persp3d(x, y, volcano2, col = map2color(volcano2, heat.colors(100)))
I switched the palette to heat.colors just for some variety.

R: Plotting a scatterplot over a filled.contour plot

I am very new to R and have made a filled.contour plot using interpolated data like the data found in Plotting contours on an irregular grid . Using some sample data from Plotting contours on an irregular grid , I made a filled.contour and simple scatterplot using the following codes
x <- datr$Lat
y <- datr$Lon
z <- datr$Rain
require(akima)
fld <- interp(x,y,z)
filled.contour(fld)
plot(x,y)
Is there a way to make the plot(x,y) and filled.contour(fld) on the same plot (overlaying)? I have tried the points(x,y), but this doesn't match the x and y axes. In Matlab, I believe I would do this with hold, but I am unsure how to do it on R.
Thanks!
You could use the arguments plot.title or plot.axes for that:
x <- 10*1:nrow(volcano)
y <- 10*1:ncol(volcano)
filled.contour(x, y, volcano, plot.title = {
points(x = 200, y = 200)
})
(via)
One way is to read the code for filled.contour, and do a
little hacking like so:
Make your figure:
filled.contour(fld)
Define these constants by copying them from the arguments list.
nlevels = 20
zlim = range(z, finite = TRUE)
las = 1
levels = pretty(zlim, nlevels)
xlim = range(x, finite = TRUE)
ylim = range(y, finite = TRUE)
xaxs = "i"
yaxs = "i"
asp = NA
Calculate these values by copying code from the function body
mar.orig <- (par.orig <- par(c("mar", "las", "mfrow")))$mar
w <- (3 + mar.orig[2L]) * par("csi") * 2.54
Set the layout by copying code from the function body
layout(matrix(c(2, 1), ncol = 2L), widths = c(1, lcm(w)))
Noteice that the figure is actually plotted after the color scale,
but we don't wnat to reverse the order of the layout because layout
actually sets the 'current' region as the last region because the
first call to plot.new will cause the current region to wrap around
to the first region. Hence, when you set the plot window and plot the points via:
plot.window(ylim=ylim,xlim=xlim)
points(x,y)
title(main='title',
sub='Sub-Title',
xlab='This is the x axis',
ylab='This is the y axis')
They overlay figure as desired.

R - How to set the range of the colorscale in a hexbin plot

I am making a scatter plot matrix using hexbin plots to show the density of certain areas.
Example:
library(lattice)
library(hexbin)
splom(cbind(rnorm(10000),rnorm(10000),rnorm(100),rnorm(100)),
,varnames = c("A","B","C","D")
,panel = panel.hexbinplot
,lower.panel = function(x, y, ...) {
panel.fill(col = brewer.pal(9, "Greys")[ round(cor(x, y,method = "spearman") * 4 + 2)])
cpl <- current.panel.limits()
panel.text(mean(cpl$xlim), mean(cpl$ylim), round(cor(x, y,method = "spearman"),2), font=2)
}
,upper.panel = function(x, y, ...){
panel.hexbinplot(x, y, type = "r", xbins = 10, ...)
}
,pscale=0, varname.cex=1, xlab = ""
)
It seems to me, that the colorscale, i.e. which count applies to which color, is recalculated in each of the 6 hexbin plots. It doesn't make a difference here but it does in my data. How can I set all these to ONE scale, meaning that a hexagon with 25 counts has the same color in all 6 plots, no matter if the maximum count in the plot is 25 or 150.
Thanks a lot in advance.
Maybe too late, but if somebody else is having the same question...Try using the argument maxcnt, it worked for me using the package Opeanair. I generated 4 plots and every one has the same color ramp: the hexagons with the same number of counts have the same color.

Surface plot Q in R - compable to surf() in matlab

I want to plot a matrix of z values with x rows and y columns as a surface similar to this graph from MATLAB.
Surface plot:
Code to generate matrix:
# Parameters
shape<-1.849241
scale<-38.87986
x<-seq(from = -241.440, to = 241.440, by = 0.240)# 2013 length
y<-seq(from = -241.440, to = 241.440, by = 0.240)
matrix_fun<-matrix(data = 0, nrow = length(x), ncol = length(y))
# Generate two dimensional travel distance probability density function
for (i in 1:length(x)) {
for (j in 1:length(y)){
dxy<-sqrt(x[i]^2+y[j]^2)
prob<-1/(scale^(shape)*gamma(shape))*dxy^(shape-1)*exp(-(dxy/scale))
matrix_fun[i,j]<-prob
}}
# Rescale 2-d pdf to sum to 1
a<-sum(matrix_fun)
matrix_scale<-matrix_fun/a
I am able to generate surface plots using a couple methods (persp(), persp3d(), surface3d()) but the colors aren't displaying the z values (the probabilities held within the matrix). The z values only seem to display as heights not as differentiated colors as in the MATLAB figure.
Example of graph code and graphs:
library(rgl)
persp3d(x=x, y=y, z=matrix_scale, color=rainbow(25, start=min(matrix_scale), end=max(matrix_scale)))
surface3d(x=x, y=y, z=matrix_scale, color=rainbow(25, start=min(matrix_scale), end=max(matrix_scale)))
persp(x=x, y=y, z=matrix_scale, theta=30, phi=30, col=rainbow(25, start=min(matrix_scale), end=max(matrix_scale)), border=NA)
Image of the last graph
Any other tips to recreate the image in R would be most appreciated (i.e. legend bar, axis tick marks, etc.)
So here's a ggplot solution which seems to come a little bit closer to the MATLAB plot
# Parameters
shape<-1.849241
scale<-38.87986
x<-seq(from = -241.440, to = 241.440, by = 2.40)
y<-seq(from = -241.440, to = 241.440, by = 2.40)
df <- expand.grid(x=x,y=y)
df$dxy <- with(df,sqrt(x^2+y^2))
df$prob <- dgamma(df$dxy,shape=shape,scale=scale)
df$prob <- df$prob/sum(df$prob)
library(ggplot2)
library(colorRamps) # for matlab.like(...)
library(scales) # for labels=scientific
ggplot(df, aes(x,y))+
geom_tile(aes(fill=prob))+
scale_fill_gradientn(colours=matlab.like(10), labels=scientific)
BTW: You can generate your data frame of probabilities much more efficiently using the built-in dgamma(...) function, rather than calculating it yourself.
In line with alexis_laz's comment, here is an example using filled.contour. You might want to increase your by to 2.40 since the finer granularity increases the time it takes to generate the plot by a lot but doesn't improve quality.
filled.contour(x = x, y = y, z = matrix_scale, color = terrain.colors)
# terrain.colors is in the base grDevices package
If you want something closer to your color scheme above, you can fiddle with the rainbow function:
filled.contour(x = x, y = y, z = matrix_scale,
color = (function(n, ...) rep(rev(rainbow(n/2, ...)[1:9]), each = 3)))
Finer granularity:
filled.contour(x = x, y = y, z = matrix_scale, nlevels = 150,
color = (function(n, ...)
rev(rep(rainbow(50, start = 0, end = 0.75, ...), each = 3))[5:150]))

Resources