Lines don't align in rastertoPolygons - r

I am having trouble with aligning grids on a plot I made. Basically the plots show the result of a 34x34 matrix where each point has a value of 0,1,2,3 and is colored based on this. The lines which outline the cells do not match up perfectly with the coloring of the cells. My code and image are below.
library(raster)
r<-raster(xmn=1,xmx=34,ymn=1,ymx=34,nrows=34,ncols=34)
data1<-read.csv(file ="mat_aligned.csv",row.names = 1)
numbers<-data.matrix(data1)
r[]<-numbers
breakpoints<-c(-1,0.1,1.1,2.1,3.1)
colors<-c("white","blue","green","red")
plot(r,breaks=breakpoints,col=colors)
plot(rasterToPolygons(r),add=TRUE,border='black',lwd=3)
I would appreciate any help with this!

The problem is that the base R plot and the drawing of the grid use different plotting systems. The polygons will stay constant relative to the plotting window (they will appear narrower as the window shrinks), and won't preserve their relationship to the underlying plot axes, whereas the coloured squares will resize to preserve shape. You'll probably find that you can get your grid to match better by resizing your window, but of course, this isn't ideal.
The best way to get round this is to use the specific method designed for plotting SpatialPolygonDataFrame, which is the S4 class produced by rasterToPolygons. This is, after all, how you're "meant" to create such a plot.
Here's a reprex (obviously I've had to make some random data as yours wasn't shared in the question) :
library(raster)
r <- raster(xmn = 1, xmx = 34, ymn = 1, ymx = 34, nrows = 34, ncols = 34)
r[] <- data.matrix(as.data.frame(replicate(34, sample(0:3, 34, TRUE))))
colors <- c("white","blue","green","red")
spplot(rasterToPolygons(r), at = 0:4 - 0.5, col.regions = colors)
Created on 2020-05-04 by the reprex package (v0.3.0)

It is difficult to help if you not provide a minimal self-contained reporducible example. Something like this
library(raster)
r <- raster(xmn=1,xmx=34,ymn=1,ymx=34,nrows=34,ncols=34)
values(r) <- sample(4, ncell(r), replace=T)
p <- rasterToPolygons(r)
plot(r)
lines(p)
I see what you describe, even though it is minimal. A work-around could be to only plot the polygons
colors<-c("white","blue","green","red")
plot(p, col=colors[p$layer])

Related

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.

Add curve to Lattice barchart

I hope the question is correctly posted. It is probably trivial but I am still not able to answer. I checked several options, included the info contained here, but with no fortune. Perhaps, I am still not used to Lattice commands, or the problem is actually not relevant.
I would overlap a barchart with a curve, such as (let's say) a normal standard distribution curve or the density distribution of the data.
Please consider the following data as example, representing the results of several die rolls:
e11 <- data.frame(freq = rep(seq(1, 6, 1), c(53, 46, 42, 65, 47, 44)))
plot_e11 <- barchart(e11,
horizontal = FALSE,
type = "density",
main = "Die results frequencies",
panel = function(x, ...){
panel.barchart(x, ...)
panel.abline(densityplot(e11$freq))})
print(plot_e11a)
It returns the normal barchart instead of the expected result.
How can I add a curve to the barchart, such as the one in the following example?
plot_e11b <- densityplot(e11$freq,
plot.points = FALSE)
panel.abline is the wrong panel function.
panel.abline adds a line of the form y = a + b * x, or vertical
and/or horizontal lines.
densityplot(e11$freq,
panel=function(x, ...) {
tab <- table(x)
panel.barchart(names(tab), tab/length(x),
horizontal=FALSE)
panel.densityplot(x, plot.points=FALSE)},
ylim=c(0, 0.3))

Using a raster attribute from a multi-attribute raster for colour levels in a plot in R

I have a raster object with a large number of attributes, and I would like to plot the spatial data in R and colour code it by a certain attribute. I have not been able to work out how to use the information of a particular attribute to achieve this. So far I have successfully extracted the attribute of choice using factorValues(), but I cannot determine how to now incorporate this information into the plot() function. I tried using the ratify() and level() functions mentioned in the raster package documentation, but I don’t understand how the simplified online examples can be adapted for a raster with multiple attributes.
Any advice on how to achieve this would be greatly appreciated.
# read in shapefile
shp = readOGR(".", "grid")
#convert to raster
r = raster(extent(shp))
res(r) = c(1,0.5)
ra = rasterize(shp, r)
#crop raster to desired extent
rcrop = crop(ra, extent(-12, 2, 29, 51))
# extract attribute value of interest
f = factorValues(rcrop, 1:420, layer=1, att=17, append.names=FALSE)
# here there are 420 cells in the raster and I am interested in plotting values of attribute 17 of the raster (this is currently a numeric attribute, not a factor)
#extra code to set attribute as the level to use for plotting colours???
rcrop = ratify(rcrop)
rat = levels(rcrop)[[1]] #this just extras row IDs..not what I want
#…
### plot: I want to plot the grid using 7 colours (I would ideally like to specify the breaks myself)
require(RColorBrewer)
cols = brewer.pal(7,"YlGnBu")
#set breaks
brks = seq(min(minValue(rcrop)),max(maxValue(rcrop),7))
#plot
plot(rcrop, breaks=brks, col=cols, axis.arg=arg)
The following is pretty hacky (and may perform poorly for large rasters), but I'm not sure if there's a way to link col.regions to a specified attribute.
rasterVis::levelplot does a nice job of labelling colour ramps corresponding to factor rasters, and while it provides an att argument allowing you to specify which attribute you're interested in, this seems to only modify the labelling of the ramp. Raster cell values control how the colour ramp is mapped to the raster, so it seems to me that we need to modify the cell values themselves. Maybe #OscarPerpiñán will chime in here to prove me wrong :)
We can create a simple function to substitute the original cell values with whichever attribute we want:
switch_att <- function(r, att) {
r[] <- levels(r)[[1]][values(r), att]
r
}
Let's download and import a small example polygon dataset from Natural Earth:
library(rasterVis)
library(rgdal)
require(RColorBrewer)
download.file(file.path('http://www.naturalearthdata.com',
'http//www.naturalearthdata.com/download/110m/cultural',
'ne_110m_admin_0_countries.zip'),
f <- tempfile())
unzip(f, exdir=tempdir())
shp <- readOGR(tempdir(), 'ne_110m_admin_0_countries')
rasterize the vector data:
r <- rasterize(shp, raster(raster(extent(shp), res=c(1, 1))))
And create some plots with levelplot:
levelplot(switch_att(r, 'continent'), col.regions=brewer.pal(8, 'Set2')) +
layer(sp.polygons(shp, lwd=0.5))
levelplot(switch_att(r, 'economy'), par.settings=BuRdTheme) +
layer(sp.polygons(shp, lwd=0.5))
EDIT
With Oscar's update to rasterVis, the switch_att hack above is no longer necessary.
devtools::install_github('oscarperpinan/rastervis')
levelplot(r, att='continent', col.regions=brewer.pal(8, 'Set2')) +
layer(sp.polygons(shp, lwd=0.5))
will produce the same figure as the first one above.

How to do a colored grid in R?

Suppose I have a matrix object in R with the values:
aa <- matrix(c(0,4,1,10,3,2,1,6,0), ncol=3)
And I want to make a figure like the one in the image, with that scale.
Can anyone help me with a function that can help me to do this type of figure in R? or the name of that type of figure-plot-colored-grid?
Look at the image function. For the scale you will probably want the colorscale function in the plotrix package. There are other functions that can also be used for these types of graphs: rasterImage, levelplot in the lattice package, etc. You could even create it from scratch using multiple calls to rect and other functions if you want complete control. But image is probably the quickest/easiest for what you show.
Or you could use package raster.
library(raster)
r <- raster(xmn = 0, xmx = 3, ymn = 0, ymx = 3, nrows = 3, ncols = 3)
r[] <- 1:9
plot(r)

Venn diagram proportional and color shading with semi-transparency

I have following type of count data.
A 450
B 1800
A and B both 230
I want to develop a colorful (possibly semi-transparency at intersections) like the following Venn diagram.
Note: This figure is an example hand drawn in PowerPoint, and it is not to scale.
Here is a post which discusses Venn diagram from list of clusters and co-occurring factors.
For easy solution use package venneuler:
require(venneuler)
v <- venneuler(c(A=450, B=1800, "A&B"=230))
plot(v)
For more advanced and customized solutions check package VennDiagram.
library(VennDiagram)
venn.diagram(list(B = 1:1800, A = 1571:2020), fill = c("lightblue", "green"),
alpha = c(0.5, 0.5), lwd =0, "venn_diagram.tiff")
I have recently published a new R package, eulerr, which does what you want. It is quite similar to venneuler but without its inconsistencies.
library(eulerr)
fit <- euler(c(A = 450, B = 1800, "A&B" = 230))
plot(fit)
Or you could try the shiny application for the same r package at eulerr.co
Based on second answer by Geek On Acid second suggestion ( thanks once again ) I would able sove the line problem as well. I am posting if this is relevent to other googlers !
require(VennDiagram)
venn.diagram(list(B = 1:1800, A = 1571:2020),fill = c("red", "green"),
alpha = c(0.5, 0.5), cex = 2,cat.fontface = 4,lty =2, fontfamily =3,
filename = "trial2.emf");
Even though this doesnt answer your question completely. I thought that this will be useful for other people looking to plot Venn Diagram.
One can use the venn() function from the gplots package:
http://www.inside-r.org/packages/cran/gplots/docs/venn
## modified slightly from the example given in the documentation
## Example using a list of item names belonging to the
## specified group.
##
require(gplots)
## construct some fake gene names..
oneName <- function() paste(sample(LETTERS,5,replace=TRUE),collapse="")
geneNames <- replicate(1000, oneName())
##
GroupA <- sample(geneNames, 400, replace=FALSE)
GroupB <- sample(geneNames, 750, replace=FALSE)
GroupC <- sample(geneNames, 250, replace=FALSE)
GroupD <- sample(geneNames, 300, replace=FALSE)
venn(list(GrpA=GroupA,GrpB=GroupB,GrpC=GroupC,GrpD=GroupD))
Afterwards I just add colours and transparency using illustrator.
There is an intuitive and flexible proportional plotter that you can download and run. Find it at:
http://omics.pnl.gov/software/VennDiagramPlotter.php
and
jvenn: an interactive Venn diagram viewer - GenoToul Bioinfo: http://bioinfo.genotoul.fr/jvenn/
I know that the OP asks about a solution in R but I would like to point to a web-based solution called BioVenn. It takes up to 3 lists of elements and draws a Venn diagram so that each surface is proportional to the number of elements - like this one:
In this diagram I have changed manually (via PhotoShop) the placement of the numbers as I did not like the locations chosen by BioVenn. But you can chose not to have numbers.
In theory the lists used with BioVenn shall consist of gene IDs but, in practice, it doesn't matter - the lists simply have to contain strings.
FWIW: found this package for python that does the same thing.

Resources