Align Edges of Ggplot Choropleth (Legend Title Varies)

Align edges of ggplot choropleth (legend title varies)

Here is an example:

library(gtable)
grid.draw(cbind(rbind(p1, p2, size="last"), rbind(p3, p4, size="last"), size = "first"))

Sample Image


Updated

This is a bad hack so I don't recommend to use.
Probably this will not work in future.

gt <- cbind(rbind(p1, p2, size="last"), rbind(p3, p4, size="last"), size = "first")
for (i in which(gt$layout$name == "guide-box")) {
gt$grobs[[i]] <- gt$grobs[[i]]$grobs[[1]]
}
grid.draw(gt)

Sample Image

Top to bottom alignment of two ggplot2 figures

To solve the problem using the align.plots method, specify respect=TRUE on the layout call:

grid_layout <- grid.layout(nrow=2, ncol=2, widths=c(1,2), heights=c(2,1), respect=TRUE)

ggplot2: how to align grobs to sides using arrangeGrob()?

Two arguments of textGrob function could be helpful to move the text horizontally: just and hjust. You could try to adjust those values to get what you are after. By the way, I assume that you used the gridExtra package. I have only made some changes in just and hjust of your original code. I might have gone too far to push the right text to the right with hjust = -5, and just = "right" could be sufficient.

library(gridExtra)
library(grid)
library(ggplot2)

p <- ggplot()
grobs1 <- grobTree(
gp = gpar(fontsize = 14),
textGrob(label = "Left", name = "title1",
x = unit(2.5, "lines"), y = unit(0, "lines"),
just = "left", hjust = 0, vjust = 0),
textGrob(label = " left", name = "title2",
x = grobWidth("title1") + unit(2.5, "lines"), y = unit(0, "lines"),
just = "left", hjust = 0, vjust = 0, gp = gpar(col = "red", fontface = "bold"))
)

grobs2 <- grobTree(
gp = gpar(fontsize = 14),
textGrob(label = "Right", name = "title1",
x = unit(0, "lines"),
y = unit(0, "lines"),
just = "right",
hjust = -5,
vjust = 0),
textGrob(label = " right", name = "title2",
x = grobWidth("title1") +unit(0, "lines"),
y = unit(0, "lines"),
just = "right",
hjust = -5,
vjust = 0, gp = gpar(col = "red", fontface = "bold"))
)

gg <- arrangeGrob(p, top = arrangeGrob(grobs1, grobs2, ncol = 2), padding = unit(1, "line"))
grid.newpage()
grid.draw(gg)

Sample Image

Geographical heat map of a custom property in R with ggmap

It looks to me like the map in the link you attached was produced using interpolation. With that in mind, I wondered if I could achieve a similar ascetic by overlaying an interpolated raster onto a ggmap.

library(ggmap)
library(akima)
library(raster)

## data set-up from question
map <- get_map(location=c(lon=20.46667, lat=44.81667), zoom=12, maptype='roadmap', color='bw')
positions <- data.frame(lon=rnorm(10000, mean=20.46667, sd=0.05), lat=rnorm(10000, mean=44.81667, sd=0.05), price=rnorm(10, mean=1000, sd=300))
positions$price <- ((20.46667 - positions$lon) ^ 2 + (44.81667 - positions$lat) ^ 2) ^ 0.5 * 10000
positions <- data.frame(lon=rnorm(10000, mean=20.46667, sd=0.05), lat=rnorm(10000, mean=44.81667, sd=0.05))
positions$price <- ((20.46667 - positions$lon) ^ 2 + (44.81667 - positions$lat) ^ 2) ^ 0.5 * 10000
positions <- subset(positions, price < 1000)

## interpolate values using akima package and convert to raster
r <- interp(positions$lon, positions$lat, positions$price,
xo=seq(min(positions$lon), max(positions$lon), length=100),
yo=seq(min(positions$lat), max(positions$lat), length=100))
r <- cut(raster(r), breaks=5)

## plot
ggmap(map) + inset_raster(r, extent(r)@xmin, extent(r)@xmax, extent(r)@ymin, extent(r)@ymax) +
geom_point(data=positions, mapping=aes(lon, lat), alpha=0.2)

http://i.stack.imgur.com/qzqfu.png

Unfortunately, I couldn't figure out how to change the color or alpha using inset_raster...probably because of my lack of familiarity with ggmap.

EDIT 1

This is a very interesting problem that has me scratching my head. The interpolation didn't quite have the look I thought it would when applied to real-world data; the polygon approaches by yourself and jazzurro certainly look much better!

Wondering why the raster approach looked so jagged, I took a second look at the map you attached and noticed an apparent buffer around the data points...I wondered if I could use some rgeos tools to try and replicate the effect:

library(ggmap)
library(raster)
library(rgeos)
library(gplots)

## data set-up from question
dat <- read.csv("clipboard") # load real world data from your link
dat$price_cuts <- NULL
map <- get_map(location=c(lon=median(dat$lon), lat=median(dat$lat)), zoom=12, maptype='roadmap', color='bw')

## use rgeos to add buffer around points
coordinates(dat) <- c("lon","lat")
polys <- gBuffer(dat, byid=TRUE, width=0.005)

## calculate mean price in each circle
polys <- aggregate(dat, polys, FUN=mean)

## rasterize polygons
r <- raster(extent(polys), ncol=200, nrow=200) # define grid
r <- rasterize(polys, r, polys$price, fun=mean)

## convert raster object to matrix, assign colors and plot
mat <- as.matrix(r)
colmat <- matrix(rich.colors(10, alpha=0.3)[cut(mat, 10)], nrow=nrow(mat), ncol=ncol(mat))
ggmap(map) +
inset_raster(colmat, extent(r)@xmin, extent(r)@xmax, extent(r)@ymin, extent(r)@ymax) +
geom_point(data=data.frame(dat), mapping=aes(lon, lat), alpha=0.1, cex=0.1)

Sample Image

P.S. I found out that a matrix of colors need to be sent to inset_raster to customize the overlay

Plot map with values for countries as color in R?

You could use rworldmap if you wanted less code and a coarser resolution map.

library(rworldmap)

#create a map-shaped window
mapDevice('x11')
#join to a coarse resolution map
spdf <- joinCountryData2Map(ddf, joinCode="NAME", nameJoinColumn="country")

mapCountryData(spdf, nameColumnToPlot="value", catMethod="fixedWidth")

Default categorisation, colours and legends can be altered, see this RJournal paper.

It would be faster with country codes rather than names.

rworldmap map

Display values corresponding to the USA states over the state name

Here a solution just with ggplot2.

  • Get the polygon data with usmap::us_map. (as you did)
  • Left join with your share data (Capitalise Your Region Names First)
  • Create centroids for the text annotation.
  • Those centroids and the share are best put into a separate data frame
  • Draw polygons with geom_polygon
  • Draw your labels (State abbreviation and shares) with geom_text, using paste.(you can also use annotate)
  • Pass the data separately to each layer. (Empty ggplot main call)

The advantage is the use of ggplot syntax makes control of color/ fill aesthetic very easy and you can also very easily customise line thickness and size of text.

As for the state abbreviations, I only used the first to letters - this may not be the official abbreviation. There is most certainly some vector out there how to convert this easily.

library(usmap)
library(tidyverse)

us <- usmap::us_map()

region <- str_to_title(region)

share_df <- data.frame(region, share)

us_val <-
left_join(us, share_df, by = c("full" ="region"))
#> Warning: Column `full`/`region` joining character vector and factor, coercing
#> into character vector

us_centroids <-
us_val %>%
group_by(full) %>%
summarise(centroid.x = mean(range(x)),
centroid.y = mean(range(y)),
label = unique(toupper(str_sub(full,1,2))),
share = unique(share))

ggplot() +
geom_polygon(data = us_val,
aes(x,y, group = group, fill = share > 3),
color = "black",
size = .1) +
geom_text(data = us_centroids,
aes(centroid.x, centroid.y, label = paste(label, "\n", share)),
size = 5/14*8) +
scale_fill_brewer(name = "State Share",
palette = "Blues",
labels = c(`TRUE`="More than 3",`FALSE`="Less than 3")) +
theme_void()

Sample Image

Created on 2020-05-06 by the reprex package (v0.3.0)

update
Having said that with the abbreviation - check out ?datasets::state. It contains those abbreviations (state.abb), and state names (state.name). It also contains data on the centroids (state.center). So, a lot of data already inbuilt :)

Data

region =  c("alabama", "alaska", "arizona", "arkansas", 
"california", "colorado", "connecticut", "delaware", "district of columbia",
"florida", "georgia", "hawaii", "idaho", "illinois", "indiana",
"iowa", "kansas", "kentucky", "louisiana", "maine", "maryland",
"massachusetts", "michigan", "minnesota", "mississippi", "missouri",
"montana", "nebraska", "nevada", "new hampshire", "new jersey",
"new mexico", "new york", "north carolina", "north dakota", "ohio",
"oklahoma", "oregon", "pennsylvania", "rhode island", "south carolina",
"south dakota", "tennessee", "texas", "utah", "vermont", "virginia",
"washington", "west virginia", "wisconsin", "wyoming")

share = c(1.15, 0.11, 6.21, 2.41, 8.42, 13.57, 3.57, 4.55, 7.08, 9.42, 5.21,
0.108, 9.09, 2.56, 4.51, 9.65, 6.76, 3.54, 0.17, 1.99, 6.66,
3.88, 7.31, 4.86, 4.85, 2.39, 0.25, 0.05, 0.21, 0.11, 3.86, 0.05,
7.31, 1.91, 0.41, 4.55, 0.002, 2.65, 3.14, 0.71, 1.94, 0.13,
2.2, 12.65, 0.05, 0.074, 5.79, 7.5, 0.12, 2.6, 0.33)


Related Topics



Leave a reply



Submit