How to Add Geo-Spatial Connections on a Ggplot Map

How to add geo-spatial connections on a ggplot map?

gcIntermediate returns different column names (since origin and destination is identical for i=2):

for (i in 1:3) {
inter <- as.data.frame(gcIntermediate(c(geo[i,]$orig_lon, geo[i,]$orig_lat),
c(geo[i,]$dest_lon, geo[i,]$dest_lat),
n=50, addStartEnd=TRUE))
print(head(inter, n=2))
}
lon lat
1 -119.7 36.17
2 -119.6 36.13
V1 V2
1 -119.7 36.17
2 -119.7 36.17
lon lat
1 -119.7 36.17
2 -119.5 36.24

The following lines should work:

for (i in 1:3) {
inter <- as.data.frame(gcIntermediate(c(geo[i,]$orig_lon, geo[i,]$orig_lat),
c(geo[i,]$dest_lon, geo[i,]$dest_lat),
n=50, addStartEnd=TRUE))
names(inter) <- c("lon", "lat")
p <- p + geom_line(data=inter, aes(x=lon, y=lat), color='#FFFFFF')
}

ggplot2, spatial map, add a line segment on to the border

The segment simply has the co-ordinates you gave it. A vertical line would be something like this:

kncoast <- data.frame(orig_lat=12.7571, 
orig_lon=74.87461,
dest_lat=15,
dest_lon=74.87461)

Sample Image

If you want the line to stretch across the coast of Karnataka, then something like this would be better:

kncoast <- data.frame(orig_lat=12.7571, 
orig_lon=74.87461,
dest_lat=14.75,
dest_lon=74.15)

Sample Image

geographical/geospatial map with maps() - R

The following code uses the simple features (sf) library to show a map of Chile overlaid with the provided datapoints. The bounding box is set in the parameters to st_crop and can be adjusted as needed without distorting the map. The code uses the Admin 0 - Countries shape file, which is in the public domain and free to use.

library(sf)
library(ggplot2)
library(dplyr);
library(magrittr);

# download world shapefile from
# https://www.naturalearthdata.com/downloads/
# 50m-cultural-vectors/50m-admin-0-countries-2/
# and extract zip file

world <- st_read(
# change below line to path of extracted shape file
'c:/path/to/ne_50m_admin_0_countries.shp'
);

world %<>% mutate(active = NAME_EN == 'Chile'); # used to highlight Chile

# convert the dataframe to a sf geometry object
dsf <- data %>%
rowwise %>%
mutate(geometry = list(st_point(c(longitud, latitud)))) %>%
st_as_sf(crs=st_crs(world));

# plot the map
world %>% st_crop(xmin=-90, xmax=-30, ymin=-60, ymax=-10) %>%
ggplot() +
geom_sf(aes(fill=active), show.legend=F) + # world map with Chile highlighted
geom_sf(data=dsf, color='#000000') + # point overlay
scale_fill_manual(values=c('#aaaa66', '#ffffcc')) + # country colors
scale_x_continuous(expand=c(0,0)) +
scale_y_continuous(expand=c(0,0)) +
theme_void() + # remove axis labels and gridlines
theme(panel.background=element_rect(fill='lightblue'))

The output is shown below. Note that the map does not distort regions that are cropped.

R output


Additional explanation

The sf package provides support for simple feature (sf) geometries. Simple features provide tools for working with geometries such as polygons and points. There is a cheat sheet here that provides a good overview.

Plotting the base map

As of release 3.0, ggplot2 provides native support for visualizing simple feature geometries. This allows for us to write:

world <- st_read(
# change below line to path of extracted shape file
'c:/path/to/ne_50m_admin_0_countries.shp'
);

ggplot(world) + geom_sf()

plot result - map of world

Simple feature objects are generally stored in data frames that include a column describing the geometry. This allows us to show a map of Chile like so:

 ggplot(world %>% filter(NAME_EN == 'Chile')) + geom_sf()

Or a map with Chile highlighted:

# create new geometry of world map
# cropped to (10°S, 60°S) and (90°W, 30°W)
chileregion <- world %>% st_crop(
xmin=-90,
xmax=-30,
ymin=-60,
ymax=-10)

# show region with Chile highlighted
ggplot(chileregion %>%
mutate(is.chile = factor(NAME_EN == 'Chile'))) +
geom_sf(aes(fill=is.chile), show.legend = F) +
scale_fill_manual(values=c('gray', 'red'))

base map

Plotting the points

We are given a data frame with two columns, latitude and longitude.

To convert to a simple feature, we first use st_point to create a new point with the given coordinate values:

dsf <- data %>% #begin with data
rowwise %>% # dplyr::rowwise applies mutation to each row individually
# create a geometry column that provides the point as a geometry
mutate(geometry = list(st_point(c(longitud, latitud))))

At this point, dsf is simply a data frame with a geometry column; it is not yet a simple feature object. We can use the function st_as_sf to create a sf object from the data frame. In doing so, we will also need to provide a coordinate reference system (CRS) to allow ggplot to project the coordinates provided onto the map rendering. Here we can provide ESPG 4326 as the CRS, which maps the x and y coordinates directly to lat/long:

  # call st_as_sf to convert data frame to a simple geometry object.
dsf <- st_as_sf(crs=4326);

Since dsf is now a simple geometry, you can plot as such:

> ggplot(dsf) + geom_sf()

ggplot output - points

(Note that you could also simply overlay the points on the base map with geom_point(data=data, aes(x=longitud, y=latitud)) without first converting to an sf object. This will work here because the CRS for the base map is also ESPG 4326, which maps x and y directly to longitude and latitude, respectively. Using geom_point, however, will not work in the general case when a coordinate transformation is applied to the geometry.)

Overlaying

With both points now defined as geometries, you can simply overlay:

ggplot() +
geom_sf(data=chileregion) +
geom_sf(data=dsf)

overlaying two geometries

The final plot in the original answer adds some additional visual aesthetics (e.g., blue background) to produce the final map output.

R Spatial - Boundaries Map

This is easier if you get the data as spatial objects. Then you can manipulate them to intersect the rivers with the US boundary.

library(tidyverse) # ggplot2, dplyr, tidyr, readr, purrr, tibble
library(rnaturalearth) # Rivers
library(sf)
library(urbnmapr)

states = get_urbn_map('states', sf=TRUE)

rivers10 <- ne_download(scale = "medium", type = 'rivers_lake_centerlines',
category = 'physical', returnclass = "sf")

# Outline of the US
us = st_union(states)

# Transform rivers to the same projection as states and clip to US
rivers10 <- rivers10 %>%
st_transform(st_crs(states)) %>%
st_intersection(us)

ggplot() +
geom_sf(data=states, fill = "#CDCDCD", color = "#25221E") +
geom_sf(data=rivers10, color='#000077') +
theme_minimal()

Sample Image

Created on 2019-12-26 by the reprex package (v0.3.0)

Plotting neighborhoods network to a ggplot maps

I looked under plot.nb, which is the plot method of your nb2listw output, and i think it basically makes a segment for all connections between your input.

# Now plotting countries
g = ggplot(some.eu.maps, aes(x = long, y = lat)) +
geom_polygon(aes( group = group, fill = region), colour = "black")+
geom_point(aes(region.lab.data$long, region.lab.data$lat), data = region.lab.data, size = 6)

# take out the connections from your nb object
# and assign them the lat and long in a dataframe
n = length(attributes(cS$neighbours)$region.id)
DA = data.frame(
from = rep(1:n,sapply(cS$neighbours,length)),
to = unlist(cS$neighbours),
weight = unlist(cS$weights)
)
DA = cbind(DA,region.lab.data[DA$from,2:3],region.lab.data[DA$to,2:3])
colnames(DA)[4:7] = c("long","lat","long_to","lat_to")
#plot it using geom_segment
g + geom_segment(data=DA,aes(xend=long_to,yend=lat_to),size=0.3,alpha=0.5)

This is what I got (caveat, I don't know what to do with the weights):

Sample Image

Geospatial mapping using ggplot faceting in R?

You were quite close to the solution. Your final data contains everything to get your plot.

Basically, you can use facet_grid to separate both "Year" and "Model" variables and geom_sf that will use the column "geometry" of your dataset to plot the shape (more informations here: https://ggplot2.tidyverse.org/reference/ggsf.html). Passing the value as a filling into the aes will make the rest.

Here, I used scale_fill_gradient to set the color and few functions to get the plot as close as your desired plot:

library(sf)
library(tidyverse)

ggplot() +
geom_sf(data = SpData, aes(fill = Value))+
facet_grid(Variable~Model)+
scale_fill_gradient(name = "Evapotranspiration (ET)", low = "green", high = "red",
limits = c(300,900),
breaks = c(300, 500, 700, 900))+
theme_void()+
theme(legend.position = "bottom")

Sample Image

Polygon Maps in R (spatial data)

@Yun Zhou: it looks like you are starting with point data. I believe you first need to convert your dataframe to a SpatialPointsDataFrame before you can convert the points to polygonal data (or some density function).

#dataframe from csv
df.in

# Coerce to SpatialPointsDataFrame
coordinates(df.in) = c("latitude", "longitude")
class(df.in) #it should be a sptial points data frame
plot(df.in)

Plot:



Related Topics



Leave a reply



Submit