Overlay map using ggplot2 - r

I am using ggplot2 to plot a matrix, and then I am using geom_text to add some letters in each point. Now, I was wondering if it is possible and how, overlaying a map, since the values represent the European region. This is my try:
library(ggplot2)
mat1<- melt(vals[,t.lat]) # matrix [long,lati]
mat2<- melt(names[,t.lat]) # matrix [long,lati]
p <-ggplot(mat1, aes(lon,lat, fill=val)) + geom_raster() +
geom_text(label = mat2$val,na.rm=TRUE,size=3)+
scale_fill_gradient(low = "white", high = "red",na.value="white")
The image that I get with this code is:
I would like to know if it is possible with ggplot2 adding the contour map to define the regions . Any idea about that???
Thanks in advance
Thanks for the comments. I will try to make a reproducible sample (since the original data is too much). The structure would be the same, except that the original matrix have some NA.
library(ggplot2)
#Coordinates
lati <- seq(from = 72, to = 34, by =-1)
loni <- seq(from=-13,to=34,by=1)
m1 <- array(runif(length(loni)*length(lati)),dim=c(length(loni),length(lati)))
m2 <- array(c("A","B"),dim=c(length(loni),length(lati)))
t.lat <-c(length(lati):1) #reverse latitude
mat1<- melt(m1[,t.lat]) # matrix [long,lati]
mat2<- melt(m2[,t.lat])
names(mat1) <- c("lon","lat","val")
names(mat2) <- c("lon","lat","val")
p <-ggplot(mat1, aes(lon,lat, fill=val)) + geom_raster() +
geom_text(label = mat2$val,na.rm=TRUE,size=3)+
scale_fill_gradient(low = "white", high = "red",na.value="white")
Then, I would like to overlay the area defined by the coordinates , loni and lati, which would be something similar to add a map in background.
I hope the question is clearer now with the example.
Thanks again.

Related

the borders function in ggplot did not work as expected?

I want to plot the (spatial) correlation pattern between two variables and overlapped by countries borders. I use borders() function with ggplot but the xlim and ylim didn't give the exact limit I expect, instead, they give all the country. I want to have the exact limits to overlap the data.
library(ncdf4)
library(ggplot2)
library(reshape)
library(maps)
library(stringr)
library(reshape2)
library(mapdata)
library(maptools)
ncfile <- nc_open("/Volumes/KIT/CHIRPS/index/correlation/correlation.amm.allindex.nc")
lon <- ncvar_get(ncfile, "lon")
lat <- ncvar_get(ncfile, "lat")
pr <- ncvar_get(ncfile, "prptotcorrel")
ret <- list ("lat"=lat, "lon"=lon,"pr"= pr)
##
str(ret)
######## melt function for pr
melt_pr <- function(L) {
dimnames(L$pr) <- list(lon = L$lon, lat = L$lat)
rett <- melt(L$pr, value.name ="pr")
}
######
mpr <- melt_pr(ret)
head(mpr)
#
xlims=range(mpr$lon); xlims
ylims=range(mpr$lat); ylims
gcorrelation=ggplot(data = mpr, aes(x = lon, y = lat, fill = pr)) +
geom_tile() +
borders('world', xlim=xlims, ylim=ylims, colour='black', size=.2) +
coord_fixed(xlim=xlims, ylim=ylims) +
labs(x = "Longitude", y = "Latitude") +
scale_fill_gradient2(low = "blue", high = "red", mid = "white",
midpoint = 0, limit = c(-1,1), na.value = NA, name="correlation") +
theme_bw() +
coord_fixed(1.3)
gcorrelation
I expect to have country borders that fit exactly the data.
Here is what I'd like the plot to look like. Here is the image with the countries; I want just to overlap with the exact limit of shaded data.
Welcome to stack overflow. Without having a sample of your data (as code), it will be hard to help. I believe that coord_cartesian() will do what you want instead of coord_fixed()
Instead of coord_fixed() or coord_cartesian(), use the xlim and ylim parameters of coord_map().
coord_map() projects a portion of the earth, which is approximately spherical, onto a flat 2D plane using any projection defined by the mapproj package.
(As #yake84 suggested, it would be best to present a simplified version of your problem that contains code and data so people can run and test their solutions.)
Taking a step back, if you are developing fresh code, I'd avoid outdated packages like reshape, reshape2, and some of the spatial functions. Instead build on their replacements (often developed by the same people) such as tidyr, sf, and the associated functions in ggplot2, such as ggsf().
Hi #yake84 and #wibeasley, sorry I'm pretty new on Stack overflow, thanks for your suggestions, coord_map() gave the right expected map. Thanks also for the packages suggestion.

How to clip an interpolated layer in R so it does not extend past data boundaries

I am trying to display a cross-section of conductivity in a lagoon environment using isolines. I have applied interp() and stat_contour() to my data, but I would like to clip the interpolated output so that it doesn't extend past my data points. This way the bathymetry of the lagoon in the cross-section is clear. Here is the code I have used so far:
cond_df <- read_csv("salinity_profile.csv")
di <- interp(cond_df$stop, cond_df$depth, cond_df$conductivity,
xo = seq(min(cond_df$stop), max(cond_df$stop), length = 200),
yo = seq(min(cond_df$depth), max(cond_df$depth), length = 200))
dat_interp <- data.frame(expand.grid(x=di$x, y=di$y), z=c(di$z))
ggplot(dat_interp) +
aes(x=x, y=y, z=z, fill=z)+
scale_y_reverse() +
geom_tile()+
stat_contour(colour="white", size=0.25) +
scale_fill_viridis_c() +
theme_tufte(base_family="Helvetica")
Here is the output:
interpolated plot
To help clarify, here is the data just as a geom_point() graph, and I do not want the interpolated layer going past the lower points of the graph:
cond_df%>%
ggplot(mapping=aes(x=stop, y=depth, z=conductivity, fill=conductivity)) +
geom_point(aes(colour = conductivity), size = 3) +
scale_y_reverse()
point plot
You can mask the unwanted region of the plot by using geom_ribbon.
You will need to generate a data.frame with values for the max depth at each stop. Here's one somewhat inelegant way to do that:
# Create the empty data frame for all stops
bathymetry <- data.frame(depth = as.numeric(NA),
stop = unique(cond_df$stop))
# Find the max depth for each stop
for(thisStop in bathymetry$stop){
bathymetry[bathymetry$stop==thisStop, "depth"] <- max(cond_df[cond_df$stop==thisStop, "depth"])
}
Then, you can add the geom_ribbon as the last geom of your plot, like so
geom_ribbon(data=bathymetry, aes(x=stop, ymin=depth, ymax=max(cond_df$depth)), inherit.aes = FALSE)

3-variables plotting heatmap ggplot2

I'm currently working on a very simple data.frame, containing three columns:
x contains x-coordinates of a set of points,
y contains y-coordinates of the set of points, and
weight contains a value associated to each point;
Now, working in ggplot2 I seem to be able to plot contour levels for these data, but i can't manage to find a way to fill the plot according to the variable weight. Here's the code that I used:
ggplot(df, aes(x,y, fill=weight)) +
geom_density_2d() +
coord_fixed(ratio = 1)
You can see that there's no filling whatsoever, sadly.
I've been trying for three days now, and I'm starting to get depressed.
Specifying fill=weight and/or color = weight in the general ggplot call, resulted in nothing. I've tried to use different geoms (tile, raster, polygon...), still nothing. Tried to specify the aes directly into the geom layer, also didn't work.
Tried to convert the object as a ppp but ggplot can't handle them, and also using base-R plotting didn't work. I have honestly no idea of what's wrong!
I'm attaching the first 10 points' data, which is spaced on an irregular grid:
x = c(-0.13397460,-0.31698730,-0.13397460,0.13397460,-0.28867513,-0.13397460,-0.31698730,-0.13397460,-0.28867513,-0.26794919)
y = c(-0.5000000,-0.6830127,-0.5000000,-0.2320508,-0.6547005,-0.5000000,-0.6830127,-0.5000000,-0.6547005,0.0000000)
weight = c(4.799250e-01,5.500250e-01,4.799250e-01,-2.130287e+12,5.798250e-01,4.799250e-01,5.500250e-01,4.799250e-01,5.798250e-01,6.618956e-01)
any advise? The desired output would be something along these lines:
click
Thank you in advance.
From your description geom_density doesn't sound right.
You could try geom_raster:
ggplot(df, aes(x,y, fill = weight)) +
geom_raster() +
coord_fixed(ratio = 1) +
scale_fill_gradientn(colours = rev(rainbow(7)) # colourmap
Here is a second-best using fill=..level... There is a good explanation on ..level.. here.
# load libraries
library(ggplot2)
library(RColorBrewer)
library(ggthemes)
# build your data.frame
df <- data.frame(x=x, y=y, weight=weight)
# build color Palette
myPalette <- colorRampPalette(rev(brewer.pal(11, "Spectral")), space="Lab")
# Plot
ggplot(df, aes(x,y, fill=..level..) ) +
stat_density_2d( bins=11, geom = "polygon") +
scale_fill_gradientn(colours = myPalette(11)) +
theme_minimal() +
coord_fixed(ratio = 1)

How to modify ggplot2 scatter plot

Here is my sample dataset:
df1 = data.frame(Count.amp = c(8,8,1,2,2,5,8), Count.amp.1 = c(4,4,2,3,2,5,4))
I tried
library(ggplot2)
qplot(Count.amp,Count.amp.1, data=df1)
Is there any way to plot in such a way that the size of the dot is proportional to the number of elements in each dots?
Yes, broadly speaking you are looking at creating a bubble plot, this code:
df1 = data.frame(Count.amp = c(8,8,1,2,2,5,8), Count.amp.1 = c(4,4,2,3,2,5,4))
df1$sum <- df1$Count.amp + df1$Count.amp.1
ggplot(df1, aes(x=Count.amp, y=Count.amp.1, size=sum),guide=FALSE)+
geom_point(colour="white", fill="red", shape=21)+ scale_size_area(max_size = 15)+
theme_bw()
would give you something like that:
It wasn't immediately clear to me what do yo mean by the number of elements but on principle you can pass any figures into the size= to get the desired result.

Coordinate points appropriately sized in ggplot2

I have sampled 10,000 coordinates from my data in this file. I have around 130,000 points.
https://www.dropbox.com/s/40hfyx6a5hsjuv7/data.csv
I am trying to plot these points on the Americas map using ggplot2. Here is my code.
library(ggplot2)
library(maps)
map_world <- map_data("world")
map_world <- subset(map_world, (lat >= -60 & lat <= 75))
map_world <- subset(map_world, (long >= -170 & long <= -30))
p <- ggplot(data = data_coords, legend = FALSE) +
geom_polygon(data = map_world, aes(x = long, y = lat, group = group)) +
geom_point(aes(x = lon, y = lat), shape = 19, size = 0.00001,
alpha = 0.3, colour = "red") +
theme(panel.grid.major = element_blank()) +
theme(panel.grid.minor = element_blank()) +
theme(axis.text.x = element_blank(),axis.text.y = element_blank()) +
theme(axis.ticks = element_blank()) +
xlab("") + ylab("")
png("my_plot.png", width = 8000, height = 7000, res = 1000)
print(p)
dev.off()
The points seem to cover the whole area in which they were plotted. I would like them to be more smaller to better represent a location. You can see that I've set the size to 0.00001. I was just trying to see if it has any effect but it doesn't seem to help after a certain limit. Is this the best that is possible at this resolution or could it be reduced more?
I had actually plotted around 400,000 points but only on the US map before and they looked much better like below. Hoping to get something like this. Thanks.
https://www.dropbox.com/s/8d0niu9g6ygz0wo/Clusters_reduced.png
Try playing with very small values of alpha, instead of the point size:
http://docs.ggplot2.org/0.9.3.1/geom_point.html
# Varying alpha is useful for large datasets
d <- ggplot(diamonds, aes(carat, price))
d + geom_point(alpha = 1/1000)
Edit:
Additional ideas are given in the documentation. Here's a summary:
Details
The scatterplot is useful for displaying the relationship between two continuous variables, although it can also be used with one continuous and one categorical variable, or two categorical variables. See geom_jitter for possibilities.
The bubblechart is a scatterplot with a third variable mapped to the size of points. There are no special names for scatterplots where another variable is mapped to point shape or colour, however.
The biggest potential problem with a scatterplot is overplotting: whenever you have more than a few points, points may be plotted on top of one another. This can severely distort the visual appearance of the plot. There is no one solution to this problem, but there are some techniques that can help. You can add additional information with stat_smooth, stat_quantile or stat_density2d. If you have few unique x values, geom_boxplot may also be useful. Alternatively, you can summarise the number of points at each location and display that in some way, using stat_sum.
Another technique is to use transparent points, geom_point(alpha = 0.05).
Edit 2:
Combining the details from the manual with the hints in Transparency and Alpha levels for ggplot2 stat_density2d with maps and layers in R
This might look like the solution:
library(ggplot2)
library(maps)
data_coords <- read.csv("C:/Downloads/data.csv")
map_world <- map_data("world")
map_world <- subset(map_world, (lat >= -60 & lat <= 75))
map_world <- subset(map_world, (long >= -170 & long <= -30))
p <- ggplot( data = data_coords, legend = FALSE) +
geom_polygon( data = map_world, aes(x = long, y = lat, group = group)) +
stat_density2d( data = data_coords, aes(x=lon, y=lat, fill = as.factor(..level..)), size=1, bins=10, geom='polygon') +
scale_fill_manual(values = c("yellow","red","green","royalblue", "black","white","orange","brown","grey"))
png("my_plot2k.png", width = 2000, height = 2000, res = 500)
print(p)
dev.off()
Resulting image (not the best colour palette used):

Resources