add 2D image on 3D Plot RGL Device with rayshader in R - r

I want to add image on 3D plot which is shown on RGL Device. I try add image with annotation_raster() and annotation_custom() but image include be 3D, i expect it be flat. are there code can i use? Thanks..
I try this code but image include 3D, not flat.
image <- magick::image_read("image.png")
image <- rasterGrob(image, interpolate = TRUE,
width=unit(1.5,'cm'),
x = unit(1,"npc"), y = unit(1,"npc"),
hjust = 1, vjust=1)
map <- sf::st_read('map/map.shp', quiet = TRUE)
gg <- ggplot(map) +
geom_sf()+
geom_sf(aes(fill =AREA),linewidth=0.7,colour='black') +
scale_fill_gradient('Area',low='skyblue',high = 'dodgerblue4',na.value = 'white')+
annotation_custom(image)+
theme_bw()+
theme(axis.line = element_blank(),axis.title = element_blank(),
axis.ticks = element_blank(), axis.text = element_blank()
)
plot_gg(gg, height = 8.5, width = 9,
multicore = TRUE,windowsize = c(1050, 600),
offset_edges = TRUE)
capture output my code

There could be some alternatives. One approach that I have used in my work is to use ggimage::geom_image(aes(x = 20, y = 30, image= "image.png"), size = 1) (adjust those numbers according to your data and original image size) to replace annotation_custom(image). This will give a 2D image instead of a 3D image on 3D graph. It worked on my machine with my data.
If it does not work on your side, please provide your data (reproducible example) so I would be able to test it on my side.

Related

Using grid to create and save a small png file

I am using R to create a number of small graphics that will be saved as PNG files, typically at 50x50 pixels, which for eventual use in a much larger image as icons or markers. As the content changes frequently, it is desirable that these be created programmatically rather than manually.
Because the content is also simple - a few characters of text and some numbers - the grid functions seemed like a straightforward way to tackle this. I don't know grid at all well as I typically use higher-level libraries such as ggplot2. The MRE below lays out what I have already achieved.
This generates output, but I am having problems linking the sizes and scales of viewport and the various grobs to the ultimate PNG file. What I get is the below, which is fine at first glance, but is a 480x480 pixel image, most of which is unused, with the central graphic taking up only a third of the width and height.
That seems logical given the viewport sizing (=.3), but if I enlarge the viewport, then presumably I have to enlarge the text and so on. (I know how to change the png() parameters to adjust the density, number of pixels and so on, but at this point the image itself is the issue.)
The question boils down to how to best generate a decent-quality 50x50 pixel PNG or SVG file from a graphic such as this, created in R, either using grid or some other approach.
library(grid)
grid.newpage()
png(bg = "transparent")
pushViewport(viewport(width=.3, height=.3, clip="off"))
grid.rect(gp=gpar(lty=0, fill="#008000"))
grid.text("15.5", x = unit(0.5, "npc"), y = unit(0.75, "npc"),
just = "center", hjust = NULL, vjust = NULL, rot = 0,
check.overlap = FALSE, default.units = "npc",
name = NULL, gp = gpar(fontsize=48), draw = TRUE, vp = NULL)
grid.text("13h 20m", x = unit(0.5, "npc"), y = unit(0.25, "npc"),
just = "center", hjust = NULL, vjust = NULL, rot = 0,
check.overlap = FALSE, default.units = "npc",
name = NULL, gp = gpar(fontsize=32), draw = TRUE, vp = NULL)
lg <- linesGrob(x = unit(c(0, 1), "npc"),
y = unit(c(0.5, 0.5), "npc"),
gp = gpar(lwd=2))
grid.draw(lg)
dev.off()
magic library may be helpful for that. I used your starting codes to create an empty png file.
library(grid)
grid.newpage()
png(bg = "transparent")
pushViewport(viewport(width=.3, height=.3, clip="off"))
dev.off()
Then I read that png file to put inside the magic codes as below. Actually, there may exist a way to put the png file directly into the magic in your R session without making temporary write - read works. However ,if you have got a lot of files to create and save as png, it is not so important to read an empty png file once. Since it can be used as for all new outputs.
library(magick)
img <- image_read("./desktop/Rplot001.png")
output <- img %>% image_background("#008000") %>% image_resize("50x50") %>%
image_annotate("15.5", size = 17, gravity = "north", location = "+1+4",color = "black", boxcolor = NULL) %>%
image_annotate("13h 20m", size = 11, gravity = "south", location = "+0+7",color = "black", boxcolor = NULL)
image_write(output, path = "./desktop/output.png", format = "png")
It gives a 50x50 png file,

How can I format the axes in plotRGB from the R raster package?

I'm trying to plot two plots side by side. One is a RasterStack for which I'm using plotRGB(). The axes are a mess however - it is plotting too many decimal places for the latitude and longitude. I'd also like to change the font size and text orientation.
This is straightforward in plot(), but I can't figure it out for plotRGB.
Can anyone help?
This is the code:
par(mar=c(4,5,4,2), mfrow = c(1, 2))
plotRGB(tayRGB, axes = TRUE, stretch = "lin", main = "RGB")
plot(knr, main = "Kmeans", cex.axis=0.96, col = viridis_pal(option="D")(10))
Can I recommend to use the function RStoolbox)::ggRGB instead of plotRGB. This will give you the full functionality of ggplot to customise your plot. A reproducible example:
set.seed(123)
R = raster(matrix(runif(400),20,20))
G = raster(matrix(runif(400),20,20))
B = raster(matrix(runif(400),20,20))
tayRGB = brick(list(R,G,B))
library(RStoolbox)
p1 = ggRGB(tayRGB, r=1, g=2, b=3, stretch = 'lin') +
scale_y_continuous(labels = scales::number_format(accuracy = 0.001)) +
scale_x_continuous(labels = scales::number_format(accuracy = 0.1)) +
theme(axis.title.x = element_text(size = 30),
axis.text.y = element_text(angle = 45))
p1
To plot your other plot side by side with this, you can either remake it as a ggplot. Or you can use ggplotify::base2grob to convert a base R plot into a grob.
p2 = ggplotify::base2grob(~plot(rnorm(100)))
cowplot::plot_grid(p1,p2)

I want to adjust the graph area in ggplot2

I made the following graph using the geomnet package and ggplot2. Then exported it to a pdf. But the graph by itself seems to be larger than the graphing area. it seems to be framed in a small square, as you can see in this picture:
graph
I don't know how to change the size of the square that's framing my graph so that the net nodes will be shown fully in my pdf. Thanks in advance.
Here's the code i'm using, and a data example:
red_list<-data_frame(From=c("A","B","C","D","D"),To=c("C","C","D","Z","A"))
red_list%>%ggplot(aes(from_id=From,to_id=To))+
geom_net(layout.alg = "circle", labelon = TRUE,
size = 12, directed = TRUE, fontsize=2, vjust = 0.5, labelcolour = "grey80",
arrowsize = 1.5, linewidth = 0.5, arrowgap = 0.05, col="darkred",
selfloops = F, ecolour = "grey40") +
theme_net() +
theme(plot.title=element_text(hjust=.5),
plot.subtitle=element_text(hjust=.5))+
ggtitle(label=paste("Figura",i,sep=" "),subtitle = paste("Interacciones entre los sectores de",names(red_list)[i],by=" ")))
I'm not sure how well it will work with graphs, but I uselly play with coord_cartesian(xlim = c(...,...), ylim = c(...,...) to adjust the plotting area.

Can you plot a table onto a ggmap similar to annotation_custom method for non- Cartesian coordinates

I have been playing around with ggplot2 a bunch and found Adding table within the plotting region of a ggplot in r
I was wondering is there any method for this for plotting using non cartesian coordinates, eg if map coordinates were used for the positioning of the table. I had some maps and thought it would be cool if they could have their corresponding data in a table for points to show more detail.
If anyone knows a work around for annotation_custom for non cartesian coordinates it would be greatly appreciated.
EDIT:Here is a image of what my map looks like, I was just thinking is there another way to plot the table on the left side of this.
EDIT: here is what Im attempting to do
EDIT: Here is the basic code structure for the plot
library(ggplot2)
library(ggmap)
plotdata <- read.csv("WellSummary_All_SE_NRM.csv", header = T)
plotdata <- na.omit(plotdata)
plotdata <- plotdata[1:20, c("Unit_No","neg_decimal_lat", "decimal_long", "max_drill_depth", "max_drill_date")]
map.plot<- get_map(location = c(min(plotdata$decimal_long),
min(plotdata$neg_decimal_lat),
max(plotdata$decimal_long),
max(plotdata$neg_decimal_lat)),
maptype ="hybrid",source = "google", zoom=8)
theme_set(theme_bw(base_size = 8))
colormap <- c("darkblue","blue","lightblue", "green", "yellow", "orange","darkorange", "red", "darkred")
myBreaks <- c(0,2, 10, 50, 250, 1250, 2000, 2500)
static.map <- ggmap(map.plot) %+% plotdata +
aes(x = decimal_long,
y = neg_decimal_lat,
z= max_drill_depth)+
stat_summary2d(fun = median, binwidth = c(.03, .03),alpha = 0.7) +
scale_fill_gradientn(name = "depth", colours= colormap, breaks=myBreaks,labels = format(myBreaks),
limits= c(0,2600), space = "Lab") +
labs(x = "Longitude",y = "Latitude")+
geom_text(aes(label=Unit_No),hjust=0, vjust=0,size=2,
position = position_dodge(width=0.9), angle = 45)+
coord_map()
#Creates image of the plot in file to Working Directory
filename=paste("2dmap",".png", sep="")
cat("\t",filename,"file created, saving...\n")
print(static.map)
cat("\tpassed mapping, file now being made\n")
ggsave(filename=filename,
plot = static.map,
scale = 1,
width = 6, height = 4,
dpi = 300)
I will try to upload the data today, cheers for some of the pointers already!
I have uploaded the data, dont worry about the positioning of the gradient values and text tags as I can fix them later I will also link the current ggmap code but I am using a very large loop for the data to be sorted.
https://drive.google.com/file/d/0B8qOIJ-nPp9rM1U1dkEzMUM0Znc/edit?usp=sharing
try this,
library(gridExtra)
grid.arrange(tableGrob(head(iris)), qplot(1,1), ncol=2)
annotation_custom wouldn't help, it's meant for adding things inside the plot panel, not to the side.

How to manipulate y-axis text labels in R varImpPlot?

The following sample resembles my dataset:
require(randomForest)
alpha = c(1,2,3,4,5,6)
bravo = c(2,3,4,5,6,7)
charlie = c(2,6,5,3,5,6)
mydata = data.frame(alpha,bravo,charlie)
myrf = randomForest(alpha~bravo+charlie, data = mydata, importance = TRUE)
varImpPlot(myrf, type = 2)
I cannot seem to control the placement of the y-axis labels in varImpPlot. I have tried altering the plot parameters (e.g. mar, oma), with no success. I need the y-axis labels shifted to the left in order to produce a PDF with proper label placement.
How can I shift the y-axis labels to the left?
I tried to use adj parameter but it produces a bug. As varImpPlot , use dotchart behind, Here a version using lattice dotplot. Then you can customize you axs using scales parameters.
imp <- importance(myref, class = NULL, scale = TRUE, type = 2)
dotplot(imp, scales=list(y =list(cex=2,
at = c(1,2),
col='red',
rot =20,
axs='i') ,
x =list(cex=2,col='blue')) )
You can extract the data needed to construct the plot out of myref and construct a plot with ggplot. By doing so you have more freedom in tweaking the plot. Here are some examples
library(ggplot2)
str(myrf)
str(myrf$importance)
data <- as.data.frame(cbind(rownames(myrf$importance),round(myrf$importance[,"IncNodePurity"],1)))
colnames(data) <- c("Parameters","IncNodePurity")
data$IncNodePurity <- as.numeric(as.character(data$IncNodePurity))
Standard plot:
(p <- ggplot(data) + geom_point(aes(IncNodePurity,Parameters)))
Rotate y-axis labels:
(p1 <- p+ theme(axis.text.y = element_text(angle = 90, hjust = 1)))
Some more tweaking (also first plot shown here):
(p2 <- p1 + scale_x_continuous(limits=c(3,7),breaks=3:7) + theme(axis.title.y = element_blank()))
Plot that looks like the varImpPlot (second plot shown here) :
(p3 <- p2+ theme(panel.grid.major.x = element_blank(),
panel.grid.minor.x = element_blank(),
panel.grid.minor.y = element_blank(),
panel.grid.major.y = element_line(colour = 'gray', linetype = 'dashed'),
panel.background = element_rect(fill='white', colour='black')))
Saving to pdf is easy with ggplot:
ggsave("randomforestplot.pdf",p2)
or
ggsave("randomforestplot.png",p2)
p2
p3
Did I understood correctly, that you want to get texts charlie and bravo more left of the boundary of the plot? If so, here's one hack to archive this, based on the modification of the rownames used in plotting:
myrf = randomForest(alpha~bravo+charlie, data = mydata, importance = TRUE)
#add white spaces at the end of the rownames
rownames(myrf$importance)<-paste(rownames(myrf$importance), " ")
varImpPlot(myrf, type = 2)
The adj parameter in dotchart is fixed as 0 (align to right), so that cannot be changed without modifying the code of dotchart:
mtext(labs, side = 2, line = loffset, at = y, **adj = 0**, col = color,
las = 2, cex = cex, ...)
(from dotchart)
EDIT:
You can make another type of hack also. Take the code of dotchart, change the above line to
mtext(labs, side = 2, line = loffset, at = y, adj = adjust_ylab, col = color,
las = 2, cex = cex, ...)
Then add argument adjust_ylab to the argument list, and rename the function as for example dotchartHack. Now copy the code of varImpPlot, find the line which calls dotchart, change the function name to dotchartHack and add the argument adjust_ylab=adjust_ylab to function call, rename the function to varImpPlotHack and add adjust_ylab to this functions argument list. Now you can change the alignment of the charlie and bravo by changing the parameter adjust_ylab:
myrf = randomForest(alpha~bravo+charlie, data = mydata, importance = TRUE)
varImpPlotHack(myrf, type = 2,adjust_ylab=0.5)
From ?par:
The value of adj determines the way in which text strings are
justified in text, mtext and title. A value of 0 produces
left-justified text, 0.5 (the default) centered text and
right-justified text. (Any value in [0, 1] is allowed, and on most
devices values outside that interval will also work.)

Resources