Reduce file size of a plot (R) (plotly) - r

I've created a map in R using ggplotly. To create a link, it needs to be 524kb or under, but it currently is 1.2Mb. Are there any good ways of reducing file size so I can export it? Or is this totally unrealistic?

If your map has polygons, consider rmapshader::ms_simplify(), which uses the Visvalingam algorithm to reduce the number of points used to construct a polygon.
Here's a reproducible example:
> p <- raster::shapefile(system.file("external/lux.shp", package="raster")) # load data
> p2 <- rmapshaper::ms_simplify(p, keep_shapes = TRUE) # simplify polygons
Now visualize the result:
> par(mfrow = c(1,2))
> plot(p, main = paste("before:", object.size(p), "bytes"))
> plot(p2, main = paste("after:", object.size(p2), "bytes"))
> dev.off()
You can edit the default settings on the keep argument, lowering the number of points to retain, and thus further reducing your object size. This comes at the cost of a coarser image.

Related

How can i use "rasterVis" package to overlay two raster and display well?

I want to overlay two raster objects.
I asked the question(Raster overlay visualization in rasterVis package: How the Significant raster images are represented as point marks?).
I refer to the #thiagoveloso'answer from this(Adding stippling to image/contour plot).
But the display is not what I wanted. It's not obvious and beautiful. If I try to change the shape or size of the mark, it will take a long long long time to draw or become weird.
Here is my code:
library(raster)
library(rasterVis)
rm(list = ls())
MK<-raster("C:/e_Zs——trend.tif")
### MK<1.96 set value to NA
fun <- function(x) { x[x<3] <- NA; return(x) }
MK<-calc(MK,fun = fun)
## load trend
Trend<- raster("C:/e_slope_trend.tif")
# And this is the key step:
# Converting the "mask" raster to spatial points
r.mask <- rasterToPoints(MK, spatial=TRUE)
plot(r.mask,cex=0.01)
# Plot
levelplot(Trend, margin=NA,par.settings=RdBuTheme) +
latticeExtra::layer(sp.points(r.mask, pch=100, cex=0.1, alpha=0.3,col="Black"))
I want to draw a fig,like:
And the fig like:
If i change the cex=0.5,it will lke:
If I change the shape of the mark, it will do so long... So. get any idea?

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)

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.

Trying to determine why my heatmap made using heatmap.2 and using breaks in R is not symmetrical

I am trying to cluster a protein dna interaction dataset, and draw a heatmap using heatmap.2 from the R package gplots. My matrix is symmetrical.
Here is a copy of the data-set I am using after it is run through pearson:DataSet
Here is the complete process that I am following to generate these graphs: Generate a distance matrix using some correlation in my case pearson, then take that matrix and pass it to R and run the following code on it:
library(RColorBrewer);
library(gplots);
library(MASS);
args <- commandArgs(TRUE);
matrix_a <- read.table(args[1], sep='\t', header=T, row.names=1);
mtscaled <- as.matrix(scale(matrix_a))
# location <- args[2];
# setwd(args[2]);
pdf("result.pdf", pointsize = 15, width = 18, height = 18)
mycol <- c("blue","white","red")
my.breaks <- c(seq(-5, -.6, length.out=6),seq(-.5999999, .1, length.out=4),seq(.100009,5, length.out=7))
#colors <- colorpanel(75,"midnightblue","mediumseagreen","yellow")
result <- heatmap.2(mtscaled, Rowv=T, scale='none', dendrogram="row", symm = T, col=bluered(16), breaks=my.breaks)
dev.off()
The issue I am having is once I use breaks to help me control the color separation the heatmap no longer looks symmetrical.
Here is the heatmap before I use breaks, as you can see the heatmap looks symmetrical:
Here is the heatmap when breaks are used:
I have played with the cutoff's for the sequences to make sure for instance one sequence does not end exactly where the other begins, but I am not able to solve this problem. I would like to use the breaks to help bring out the clusters more.
Here is an example of what it should look like, this image was made using cluster maker:
I don't expect it to look identical to that, but I would like it if my heatmap is more symmetrical and I had better definition in terms of the clusters. The image was created using the same data.
After some investigating I noticed was that after running my matrix through heatmap, or heatmap.2 the values were changing, for example the interaction taken from the provided data set of
Pacdh-2
and
pegg-2
gave a value of 0.0250313 before the matrix was sent to heatmap.
After that I looked at the matrix values using result$carpet and the values were then
-0.224333135
-1.09805379
for the two interactions
So then I decided to reorder the original matrix based on the dendrogram from the clustered matrix so that I was sure that the values would be the same. I used the following stack overflow question for help:
Order of rows in heatmap?
Here is the code used for that:
rowInd <- rev(order.dendrogram(result$rowDendrogram))
colInd <- rowInd
data_ordered <- matrix_a[rowInd, colInd]
I then used another program "matrix2png" to draw the heatmap:
I still have to play around with the colors but at least now the heatmap is symmetrical and clustered.
Looking into it even more the issue seems to be that I was running scale(matrix_a) when I change my code to just be mtscaled <- as.matrix(matrix_a) the result now looks symmetrical.
I'm certainly not the person to attempt reproducing and testing this from that strange data object without code that would read it properly, but here's an idea:
..., col=bluered(20)[4:20], ...
Here's another though which should return the full rand of red which tha above strategy would not:
shift.BR<- colorRamp(c("blue","white", "red"), bias=0.5 )((1:16)/16)
heatmap.2( ...., col=rgb(shift.BR, maxColorValue=255), .... )
Or you can use this vector:
> rgb(shift.BR, maxColorValue=255)
[1] "#1616FF" "#2D2DFF" "#4343FF" "#5A5AFF" "#7070FF" "#8787FF" "#9D9DFF" "#B4B4FF" "#CACAFF" "#E1E1FF" "#F7F7FF"
[12] "#FFD9D9" "#FFA3A3" "#FF6C6C" "#FF3636" "#FF0000"
There was a somewhat similar question (also today) that was asking for a blue to red solution for a set of values from -1 to 3 with white at the center. This it the code and output for that question:
test <- seq(-1,3, len=20)
shift.BR <- colorRamp(c("blue","white", "red"), bias=2)((1:20)/20)
tpal <- rgb(shift.BR, maxColorValue=255)
barplot(test,col = tpal)
(But that would seem to be the wrong direction for the bias in your situation.)

Clearing plotted points in R

I am trying to use the animation package to generate an "evolving" plot of points on a map. The map is generated from shapefiles (from the readShapeSpatial/readShapeLines functions).
The problem is when it's plotted in a for loop, the result is additive, whereas the ideal result is to have it evolve.
Are there ways of using par() that I am missing?
My question is: is there a way to clear just the points ploted from the points function
and not clearing the entire figure thus not having to regraph the shapefiles?
in case someone wants to see code:
# plotting underlying map
newyork <- readShapeSpatial('nycpolygon.shp')
routes <- readShapeLines('nyc.shp')
par(bg="grey25")
plot(newyork, lwd=2, col ="lightgray")
plot(routes,add=TRUE,lwd=0.1,col="lightslategrey")
# plotting points and save to GIF
ani.options(interval=.05)
saveGIF({
par(bg="grey25")
# Begin loop
for (i in 13:44){
infile <-paste("Week",i,".csv",sep='')
mydata <-read.csv(file = infile, header = TRUE, sep=",")
plotvar <- Var$Para
nclr <- 4
plotclr <-brewer.pal(nclr,"RdPu")
class<- classIntervals(plotvar,nclr,style = "pretty")
colcode <- findColours(class,plotclr)
points(Var$Lon,Var$Lat,col=colcode)
}
})
If you can accept a residual shadow or halo of ink, you can over-plot with color ="white" or == to your background choices. We cannot access your shape file but you can try it out by adding this line:
points(Var$Lon, Var$Lat, col="grey25")
It may leave gaps in other previously plotted figures or boundaries, because it's definitely not object-oriented. The lattice and ggplot2 graphics models are more object oriented, so if you want to post a reproducible example, that might be an alternate path to "moving" forward. I seem to remember that the rgl package has animation options in its repetoire.

Resources