How can I map raster and vector data together? - r

I want to map raster and vector data in R
Data
class(Africa)# SpatialPolygonsDataFrame
class(Rift)#SpatialLinesDataFrame
class(Data.SP)#SpatialPointsDataFrame
class(An_Precip_subTest)#RasterLayer`
Code I am trying to run
tm_shape(Africa) +
tm_raster(An_Precip_subTest)+
tm_shape(Data.SP) +
tm_dots(col="CS", auto.palette.mapping = FALSE, palette="-RdYlBu",
breaks=Spectrum, title="Ventral Centroid Size", size=0.3)+
tm_shape(Rift) + tm_lines(col = "black") +
tm_legend(legend.outside=TRUE)
I get this error message
Error: Africa consists of polygons, so it cannot accept tm_raster.
I have modeled my code after the tmap in a nutshell examples
(https://cran.r-project.org/web/packages/tmap/vignettes/tmap-nutshell.html)
tm_shape(land) +
tm_raster("trees", breaks=seq(0, 100, by=20), legend.show = FALSE) +
tm_shape(Europe, is.master = TRUE) +
tm_borders() +
tm_shape(rivers) +
tm_lines(lwd="strokelwd", scale=5, legend.lwd.show = FALSE) +
tm_shape(metro) +
tm_bubbles("pop2010", "red", border.col = "black", border.lwd=1,
size.lim = c(0, 11e6), sizes.legend = c(1e6, 2e6, 4e6, 6e6, 10e6),
title.size="Metropolitan Population") +
tm_text("name", size="pop2010", scale=1, root=4, size.lowerbound = .6,
bg.color="white", bg.alpha = .75,
auto.placement = 1, legend.size.show = FALSE) +
tm_format_Europe() +
tm_style_natural()
They just drop a raster file in after a shape file and everything works out fine.
I do not understand how my code is different and incorrect.
I used this example
(https://gis.stackexchange.com/questions/61243/clipping-a-raster-in-r) to make my raster file
I wonder if others have had trouble recreating this example
How can I map raster and vector data together?
I am up for trying new packages, converting data to different formats etc
Any help is appreciated.

Although an old question. But maybe the solution is helpful for other people. To plot the vector (shape file overlaid with raster), first run tm_raster() + tm_shape (your shapefile (sp,sf object)) + tm_dots (in case your shape file is points object)

Related

How can I make a transition to a linear model?

From a database called "datoschile" that incorporates 6 variables, I have created a panel data called "magrupados3" that uses the variable "Periodo" as an identity variable and I have filtered thstrong texte information using only "Importaciones" and "Exportaciones" variables
This the excel file needed to work with this code
https://gitlab.com/pedritoandrade/how-can-i-make-a-transition-to-a-linear-model
datos <- read.xlsx("C:\\Users\\PEDRO ANDRADE 2019\\Desktop\\Curso Betametrica\\Analisis exploratorio y automatizacion de reportes\\datoschile.xlsx",
sheet = "Hoja1",
detectDates = T)`
magrupados3 <- melt(datos, id.vars = "Periodo")%>%
filter(variable == "Exportaciones" | variable == "Importaciones")`
Then with this data, I have created a graph using geom_line and geom_point and also the tendency line using geom_smooth. This is the code and the result you can see it here:
magrupados4 <- ggplot(data=magrupados3,aes(x=Periodo,y=value))+
geom_line()+geom_point()+facet_wrap(variable~.,scales = "free",ncol = 2)+
geom_smooth(method = "lm",formula= y~x,col="black",se=F)`
Graph
I want to make a transition of this graph. In other words, I want that geom_line and the regression line (geom_smooth) to appear simultaneously each year(my variable that represents year in my data is called "Periodo").
Can someone help me with this?
It seems that you need to use the R package gganimate in combination with the R packages: devtools, ggplot2, gifski, and av.
Check this link: https://gganimate.com/
Here is an example that I took from that website. It is working in my computer. You need the libraries that are in my example. Some libraries were not in the website example. Be careful with that. In your code, you did not use the last two lines of this example (transition_time(year) + ease_aes('linear')). Also, I guess that you did not install all the R libraries that are needed.
# install.packages('devtools')
# devtools::install_github('thomasp85/gganimate')
library(devtools)
library(gapminder)
library(ggplot2)
library(gganimate)
library(gifski)
library(av)
ggplot(gapminder, aes(gdpPercap, lifeExp, size = pop, colour = country)) +
geom_point(alpha = 0.7, show.legend = FALSE) +
scale_colour_manual(values = country_colors) +
scale_size(range = c(2, 12)) +
scale_x_log10() +
facet_wrap(~continent) + labs(title = 'Year: {frame_time}', x = 'GDP per capita', y = 'life expectancy')+
transition_time(year) +
ease_aes('linear')

How to give two different colors for upregulated genes and downregulated genes?

I currently have a code to make a scatterplot as shown below, I made two objects of gene names that are being downregulated and upregulated, Then I added the two objects to points (points = c(genes.to.labelCtrl, genes.to.labelCis)) so that only the labels in these two objects show up on the scatterplot. But I would like the genes.to.labelCtrl gene names to be blue in color and genes.to.labelCis gene names to be red in color. But I can't add more than one color to the LabelPoints, otherwise the code throws me an error.
p1 <- ggplot(object, aes(CTRL, CIS)) + geom_point() + ggtitle("Macrophage CTRL vs CIS") + theme(plot.title = element_text(hjust = 0.5)) + geom_point(size = 1,alpha = 0.6) +
geom_smooth(method=lm, se=TRUE, color="brown", linetype="solid", size=1)
p1 <- LabelPoints(plot = p1, points = c(genes.to.labelCtrl, genes.to.labelCis), color="blue", repel = TRUE, xnudge=0, ynudge=0)
plot_grid(p1)
Do you know how to overcome this issue?
probably it's not a good solution and won't adress your problem. But as a reproducible example was missing (as MrFlick already mentioned) and as my knowledge on genes is basically NULL, I had to be creative :D
I assumed that you have two label variables in your object dataframe and that you only want some of your CTRL/CIS values to be labeled. If that's the case I would pre calculate the label variables (based on a set of conditions you define ... here it was just a sample). In the next step I would plot both labels with geom_text and define a unique color (I am not sure what exactely LabelPoints is doing, because I had no possibility to test it ... so I sticked to your description)
I hope you can use this as a starting point (otherwise just throw it away ^^)
object <- dplyr::tibble(ID=1:100,
CTRL=rnorm(100),
CIS=rnorm(100),
label1=sample(c("","A"),size=100,replace=T,prob=c(.9,.1)),
label2=sample(c("","B"),size=100,replace=T,prob=c(.9,.1)))
ggplot2::ggplot(object,
ggplot2::aes(x=CTRL, y=CIS)) +
ggplot2::geom_point() +
ggplot2::geom_text(ggplot2::aes(label=label1),color="red") +
ggplot2::geom_text(ggplot2::aes(label=label2),color="blue") +
ggplot2::ggtitle("Macrophage CTRL vs CIS") +
ggplot2::theme(plot.title = ggplot2::element_text(hjust = 0.5)) +
ggplot2::geom_point(size = 1,
alpha = 0.6) +
ggplot2::geom_smooth(method=lm,
se=TRUE,
color="brown",
linetype="solid",
size=1)
#sambold Thank you so very much for your detailed response despite no reproducible example. Next time I have a question, I will make sure to upload an example as well.
I think I was able to figure out a simple solution.
In my initial code, I added my two gene name data frames as a vector in the “points” slot as below.
p1 <- LabelPoints(plot = p1, points = c(genes.to.labelCtrl, genes.to.labelCis), color="blue", repel = TRUE, xnudge=0, ynudge=0)
However, if I separate the gene name data frame into two R codes, then I am able to color code gene names from each gene name data frame as shown below.
p1 <- LabelPoints(plot = p1, points = genes.to.labelCtrl, color="blue", repel = TRUE, xnudge=0, ynudge=0)
p1 <- LabelPoints(plot = p1, points = genes.to.labelCis, color="red", repel = TRUE, xnudge=0, ynudge=0)

Ggvegan autoplot plot boundaries

I have done CCA- and RDA analysis in R with vegan and used autoplot.cca to generate plots. However, the plot boundaries are not constant and adjust autmatically (to what I do not know). Some plots return a horizontally very narrow plot
I have tried some suggestions like adding:
autoplot() +
labs(x=NULL, y=NULL) +
scale_x_continuous(expand = c(0, 0)) +
scale_y_continuous(expand = c(0, 0))
But this doesn't resolve anything. The code for plotting is below. I'm not making any fancy calls on formatting earlier in the code.
print(autoplot(my.cca, geom = "text", title = paste(i, "_sites_params_Wetter"), layers = c("sites", "biplot")) +
#geom_point(aes(my.cca)) +
#geom_hline(yintercept = 0) +
#geom_vline(xintercept = 0) +
theme(legend.position = "none")
)
Example output shared in link (don't have enough rep to post images):
I essentially plot in a loop, and the plots vary in area. I would like to be able to control the dimensions of the plotting area, and also make sure all labels are 100% within the area.
How do I do this?
Here is some example code to play with
x<-c("vegan", "ggplot2", "ggvegan")
lapply(x, require, character.only = TRUE)
data(package = "vegan")
data(mite)
data(mite.env)
my.cca <- cca(mite ~ ., data=mite.env)
autoplot(my.cca, geom = "text", layers = c("species", "biplot")) +
theme(legend.position = "none")

fit two sf polygons seamlessly

The problem
Suppose we have two shapefiles that should border seamlessly. Only, they don't. Is there a way to force them to stick to one another without gaps?
The specific case
I have two shapefiles: one for European regions -- REG, the other for the neighbouring countries -- NEI. Both shapefiles are taken from Eurostat repository and should fit together nicely; but there are small gaps. Also, I need to simplify the polygons, and then the gaps become really notable.
The best I can think of
I've tried several approaches but with no success. The only way to achieve the desired result that I see requires following steps:
create a line sf with just the border between my shapefiles;
from this line create a buffer polygon just big enough to cover all gaps;
join and dissolve this buffer to the shapefile for neighbours -- NEI;
clip off the expanded NEI with the REG shapefile.
Obviously, this is a rather clumsy workaround.
Is there a better way to go?
Reproducible example in this gist
A minimal example
# install dev version of ggplot2
devtools::dev_mode()
devtools::install_github("tidyverse/ggplot2")
library(tidyverse)
library(sf)
library(rmapshaper)
library(ggthemes)
# load data
source(file = url("https://gist.githubusercontent.com/ikashnitsky/4b92f6b9f4bcbd8b2190fb0796fd1ec0/raw/1e281b7bb8ec74c9c9989fe50a87b6021ddbad03/minimal-data.R"))
# test how good they fit together
ggplot() +
geom_sf(data = REG, color = "black", size = .2, fill = NA) +
geom_sf(data = NEI, color = "red", size = .2, fill = NA)+
coord_sf(datum = NA)+
theme_map()
ggsave("test-1.pdf", width = 12, height = 10)
# simplify
REGs <- REG %>% ms_simplify(keep = .5, keep_shapes = TRUE)
NEIs <- NEI %>% ms_simplify(keep = .5, keep_shapes = TRUE)
ggplot() +
geom_sf(data = REGs, color = "black", size = .2, fill = NA) +
geom_sf(data = NEIs, color = "red", size = .2, fill = NA)+
coord_sf(datum = NA)+
theme_map()
ggsave("test-2.pdf", width = 12, height = 10)
ms_simplify seems to work on your minimal example but you need first to group your 2 "shapefiles" into one "shapefile". If needed it would be easy to split them after the simplification of the boundaries.
(note : my version of rmapshaper returns an error when ms_simplify is used with an sf object. This is why I have transformed my tmp object in a sp object with as(tmp, "Spatial"))
NEI <- st_transform(NEI, st_crs(REG)$epsg)
tmp <- rbind(REG , NEI)
tmp <- ms_simplify(as(tmp, "Spatial"), keep = .1, keep_shapes = T)
ggplot() + geom_sf(data = st_as_sf(tmp)) + theme_bw()

Plot continuous raster data in binned classes with ggplot2 in R

I quite like the look and feel of ggplot2 and use them often to display raster data (e.g facetting over timesteps for time-varying precipitation fields is very useful).
However, I'm still wondering whether it is easily possible to bin the continuous raster values into discrete bins and assign to each bin a single colour, that is shown in the legend (as many GIS systems do).
I tried with the guide = "legend", and breaks arguments of the scale_fill_gradient option. However these affect just the legend on the side of the graph, but the plotted values are still continuous.
library(ggplot2)
data <- data.frame(x=rep(seq(1:10),times = 10), y=rep(seq(1:10),each = 10), value = runif(100,-10,10))
ggplot(data = data, aes(x=x,y=y)) +
geom_raster(aes(fill = value)) +
coord_equal() +
scale_fill_gradient2(low = "darkred", mid = "white", high = "midnightblue",
guide = "legend", breaks = c(-8,-4,0,4,8))
My question is mainly how to discretize the data that is plotted in ggplot, so that the reader of the graph can make quantitative conclusions on the values represented by the colors.
Secondly, how can I still use a diverging color palette (similar to scale_fill_gradient2), that is centered around zero or another specific value?
You should use the raster package to work with raster data. This
package provides several function to work with categorical
rasters. For example, with reclassify you can convert a continuous
file into a discrete raster. The next example is adapted from
this question:
library(raster)
f <- system.file("external/test.grd", package="raster")
r <- raster(f)
r <- reclassify(r, c(0, 500, 1,
500, 2000, 2))
On the other hand, if you want to use the ggplot2 functions, the
rasterVis package provides a simple wrapper around ggplot that
works with RasterLayer objects:
library(rasterVis)
gplot(r) +
geom_raster(aes(fill = factor(value))) +
coord_equal()
to define your own colors you can add then:
scale_fill_manual(values=c('red','green')))
The best is indeed to modify the underlying data set by manually discretizing it. Below answer is based on the answer by joran.
library(ggplot2)
set.seed(1)
data <- data.frame(x = rep(seq(1:10),times = 10),
y = rep(seq(1:10),each = 10),
value = runif(100,-10,10))
# Define category breaks
breaks <- c(-Inf,-3:3,Inf)
data$valueDiscr <- cut(data$value,
breaks = breaks,
right = FALSE)
# Define colors using the function also used by "scale_fill_gradient2"
discr_colors_fct <-
scales::div_gradient_pal(low = "darkred",
mid = "white",
high = "midnightblue")
discr_colors <- discr_colors_fct(seq(0, 1, length.out = length(breaks)))
discr_colors
# [1] "#8B0000" "#B1503B" "#D18978" "#EBC3B9" "#FFFFFF" "#C8C0DB" "#9184B7" "#5B4C93" "#191970"
ggplot(data = data, aes(x=x,y=y)) +
geom_raster(aes(fill = valueDiscr)) +
coord_equal() +
scale_fill_manual(values = discr_colors) +
guides(fill = guide_legend(reverse=T))
Update 2021-05-31:
Based on the comment by #slhck one can indeed discretize the data in the aesthetic mapping as follows:
library(ggplot2)
set.seed(1)
data <- data.frame(x = rep(seq(1:10),times = 10),
y = rep(seq(1:10),each = 10),
value = runif(100,-10,10))
# Define category breaks
breaks <- c(-Inf,-3:3,Inf)
discr_colors <- scales::div_gradient_pal(low = "darkred", mid = "white", high = "midnightblue")(seq(0, 1, length.out = length(breaks)))
# [1] "#8B0000" "#B1503B" "#D18978" "#EBC3B9" "#FFFFFF" "#C8C0DB" "#9184B7" "#5B4C93" "#191970"
ggplot(data = data, aes(x=x,y=y)) +
geom_raster(aes(fill = cut(value, breaks, right=FALSE))) +
coord_equal() +
scale_fill_manual(values = discr_colors) +
guides(fill = guide_legend(reverse=T))

Resources