Can't combine ggplot of shapefiles including polygons and spatialpoints - r

I downloaded three different shapefiles of the city chicago. Now i wanted to combine them and plot them together. Only the ward-offices do not plot. '''Error: data must be a data frame, or other object coercible by fortify(), not an S4 object with class SpatialPointsDataFrame'''
The first two are polygons and the third is point oriented...
this is my code:
#setting directiories
chicagodir = 'Community Areas/'
chicagoshp = paste(chicagodir, "geo_export_b982773b-13a7-4b96-827d-d969f0695777.shp", sep = "")
chicagoread =readOGR(chicagoshp)
plot(chicagoread)
#Wardprecints facilities
wardprecinctsdir = 'WardPrecincts/'
wardprecinctsshp = paste(wardprecinctsdir, "WardPrecincts.shp", sep = "")
wardprecinctsshpread =readOGR(wardprecinctsshp)
plot(wardprecinctsshpread)
#Ward Offices - Map - Exportable
wardofficesdir = 'Ward Offices - Map - Exportable/'
wardofficesshp = paste(wardofficesdir, "geo_export_b47221aa-0cc1-45db-8a3c-3e6ba72dccf1.shp", sep = "")
wardofficesshpread = readOGR(wardofficesshp)
plot(wardofficesshpread)
chicago_transform <- spTransform(chicagoread, CRS("+proj=longlat +init=epsg:4326"))
wardpre_transform <-spTransform(wardprecinctsshpread, CRS("+proj=longlat +init=epsg:4326"))
wardoff_transform <-spTransform(wardofficesshpread, CRS("+proj=longlat +init=epsg:4326"))
combinedplot = ggplot() +
geom_path(data = chicago_transform, aes(x = long, y = lat, group = group)) +
coord_fixed() +
labs(title = "Plot of Chicago",
x = "long", y = "lat") +# Because we don't need x and y labels do we?
#add specific wardprecinctsshpread and wardoffices
geom_polygon(data=wardpre_transform, aes(x = long, y = lat, group = group, color="red")) +
geom_polygon(data=wardoff_transform, aes(x = long, y = lat, group = group, color="blue"))
combinedplot
'''
How do I resolve this, the plotting of points to the 2 polygons? thankyou in advance

Indeed the ward office data is different as points. You can just use as.data.frame on SpatialPointsDataFrame for plotting.
Note that instead of lat and long you need latitude and longitude (really y and x coordinates).
Otherwise, let me know if this is what you had in mind.
library(rgdal)
library(ggplot2)
chicagoread =readOGR("geo_export_210c4709-68df-496d-8b9c-8f7484608bc9.shp")
plot(chicagoread)
wardprecinctsshpread =readOGR("WardPrecincts.shp")
plot(wardprecinctsshpread)
wardofficesshpread = readOGR("geo_export_10f18171-8b13-4022-8d57-08d3b9bb0027.shp")
plot(wardofficesshpread)
chicago_transform <- spTransform(chicagoread, CRS("+proj=longlat +init=epsg:4326"))
wardpre_transform <- spTransform(wardprecinctsshpread, CRS("+proj=longlat +init=epsg:4326"))
wardoff_transform <- spTransform(wardofficesshpread, CRS("+proj=longlat +init=epsg:4326"))
combinedplot = ggplot() +
geom_path(data = chicago_transform, aes(x = long, y = lat, group = group)) +
coord_fixed() +
labs(title = "Plot of Chicago", x = "long", y = "lat") +
geom_polygon(data=wardpre_transform, aes(x = long, y = lat, group = group), color="red") +
geom_point(data=as.data.frame(wardoff_transform), aes(x = longitude, y = latitude), color="blue") +
theme_bw()
combinedplot

Related

Using geom_text() to display text in geom_polygon() [duplicate]

I am trying to label my polygons by using ggplot in R. I found a topic here on stackoverflow that I think is very close to what I want except with points.
Label points in geom_point
I found some methods online. Now I first need to find the central location of each shape and then I have to put these locations together with the name together. Then link this to the labeling function in geom_text()
ggplot centered names on a map
Since I have been trying for a long time now I decided to ask the question and hope that someone here can give me the final push to what I want. My plotting function:
region_of_interest.fort <- fortify(region_of_interest, region = "score")
region_of_interest.fort$id <- as.numeric(region_of_interest.fort$id)
region_of_interest.fort$id <- region_of_interest.fort$id
region_of_interest.fort1 <- fortify(region_of_interest, region = "GM_NAAM")
region_of_interest.fort1$id <- as.character(region_of_interest.fort1$id)
region_of_interest.fort1$id <- region_of_interest.fort1$id
idList <- unique(region_of_interest.fort1$id)
centroids.df <- as.data.frame(coordinates(region_of_interest))
names(centroids.df) <- c("Longitude", "Latitude")
randomMap.df <- data.frame(id = idList, shading = runif(length(idList)), centroids.df)
ggplot(data = region_of_interest.fort, aes(x = long, y = lat, fill = id, group = group)) +
geom_polygon() +
geom_text(centroids.df, aes(label = id, x = Longitude, y = Latitude)) +
scale_fill_gradient(high = "green", low = "red", guide = "colorbar") +
coord_equal() +
theme() +
ggtitle("Title")
It gives me the error: ggplot2 doesn't know how to deal with data of class uneval
My data
region_of_interest$GM_NAAM
[1] Groningen Haren Ooststellingwerf Assen Aa en Hunze Borger- Odoorn
[7] Noordenveld Westerveld Tynaarlo Midden-Drenthe
415 Levels: 's-Gravenhage 's-Hertogenbosch Aa en Hunze Aalburg Aalsmeer Aalten ... Zwolle
region_of_interest$score
[1] 10 -2 -1 2 -1 -4 -4 -5 0 0
Try something like this?
Get a data frame of the centroids of your polygons from the
original map object.
In the data frame you are plotting, ensure there are columns for
the ID you want to label, and the longitude and latitude of those
centroids.
Use geom_text in ggplot to add the labels.
Based on this example I read a world map, extracting the ISO3 IDs to use as my polygon labels, and make a data frame of countries' ID, population, and longitude and latitude of centroids. I then plot the population data on a world map and add labels at the centroids.
library(rgdal) # used to read world map data
library(rgeos) # to fortify without needing gpclib
library(maptools)
library(ggplot2)
library(scales) # for formatting ggplot scales with commas
# Data from http://thematicmapping.org/downloads/world_borders.php.
# Direct link: http://thematicmapping.org/downloads/TM_WORLD_BORDERS_SIMPL-0.3.zip
# Unpack and put the files in a dir 'data'
worldMap <- readOGR(dsn="data", layer="TM_WORLD_BORDERS_SIMPL-0.3")
# Change "data" to your path in the above!
worldMap.fort <- fortify(world.map, region = "ISO3")
# Fortifying a map makes the data frame ggplot uses to draw the map outlines.
# "region" or "id" identifies those polygons, and links them to your data.
# Look at head(worldMap#data) to see other choices for id.
# Your data frame needs a column with matching ids to set as the map_id aesthetic in ggplot.
idList <- worldMap#data$ISO3
# "coordinates" extracts centroids of the polygons, in the order listed at worldMap#data
centroids.df <- as.data.frame(coordinates(worldMap))
names(centroids.df) <- c("Longitude", "Latitude") #more sensible column names
# This shapefile contained population data, let's plot it.
popList <- worldMap#data$POP2005
pop.df <- data.frame(id = idList, population = popList, centroids.df)
ggplot(pop.df, aes(map_id = id)) + #"id" is col in your df, not in the map object
geom_map(aes(fill = population), colour= "grey", map = worldMap.fort) +
expand_limits(x = worldMap.fort$long, y = worldMap.fort$lat) +
scale_fill_gradient(high = "red", low = "white", guide = "colorbar", labels = comma) +
geom_text(aes(label = id, x = Longitude, y = Latitude)) + #add labels at centroids
coord_equal(xlim = c(-90,-30), ylim = c(-60, 20)) + #let's view South America
labs(x = "Longitude", y = "Latitude", title = "World Population") +
theme_bw()
Minor technical note: actually coordinates in the sp package doesn't quite find the centroid, but it should usually give a sensible location for a label. Use gCentroid in the rgeos package if you want to label at the true centroid in more complex situations like non-contiguous shapes.
The accepted answer here may work, but the actual question asked specifically notes that there is an error "ggplot2 doesn't know how to deal with data of class uneval."
The reason that it is giving you the error is because the inclusion of centroids.df needs to be a named variable (e.g. accompanied by "data=")
Currently:
ggplot(data = region_of_interest.fort, aes(x = long, y = lat, fill = id, group = group)) +
geom_polygon() +
geom_text(centroids.df, aes(label = id, x = Longitude, y = Latitude)) +
scale_fill_gradient(high = "green", low = "red", guide = "colorbar") +
coord_equal() +
theme() +
ggtitle("Title")
Should be (note: "data=centroids.df"):
ggplot(data = region_of_interest.fort, aes(x = long, y = lat, fill = id, group = group)) +
geom_polygon() +
geom_text(data=centroids.df, aes(label = id, x = Longitude, y = Latitude)) +
scale_fill_gradient(high = "green", low = "red", guide = "colorbar") +
coord_equal() +
theme() +
ggtitle("Title")
This issue was addressed here: How to deal with "data of class uneval" error from ggplot2?

R geom_point vs geom_line vs geom_path for US states shapefile

[US state with geom_path][1][US state with geom_point][2]I am using R to overlay US states shape file above ogallala region shape file. I would ideally like to have shape boundaries as line but I get poorly formed map when I try that (in pictures) but when I try geom_point it works alright. Can someone please explain what I am doing wrong. [US state with geom_line][3]
OG_HUC = read.csv("input/Ogallala_huc.csv")
OG_table =right_join(HUC8_map.df,OG_HUC,by = c("HUC_CODE"="HUC8"))
#OG_table = merge(HUC8_map.df,OG_HUC,by = "HUC8", sort = FALSE)
OG_table[is.na(OG_table)] = 0
#write.csv(OG_table,'OG_table.csv')
State <- readOGR(
dsn= paste0(getwd(),"/input/State") ,
layer="states"
)
State_map <- spTransform(State, CRS("+proj=longlat +datum=WGS84"))
State_map#data$id = rownames(State_map#data)
State_map.points = fortify(State_map, region="id")
centroids.df <- as.data.frame(coordinates(State_map))
names(centroids.df) <- c("Longitude", "Latitude") #more sensible column names
State_map.df1 = merge(State_map.points, State_map#data, by="id")
State_map.df2 = data.frame(id = State_map#data$id, State_map#data, centroids.df)
ggplot()+geom_polygon(data=OG_table,aes(x = long, y = lat, group=group),fill="lightskyblue",col="black", alpha = 0.3) +
geom_text(data = State_map.df2, aes(Longitude, Latitude, label=STATE_ABBR),col="black")+
#geom_path(data = OG_table, aes(long, lat, group=group),color="black") +
geom_point(data = State_map.df1, aes(long, lat, label=STATE_ABBR),color="black")+
coord_map(xlim = c(-108,-95),ylim = c(31,45))+
scale_fill_identity()
```enter image description here
[1]: https://i.stack.imgur.com/7XzeB.png
[2]: https://i.stack.imgur.com/9tAB8.png
[3]: https://i.stack.imgur.com/MtgXs.png
Try:
Library (maps)
Your_data %>% ggplot (aes(lat, lon)) +
Borders ("states") +
geom_polygon()

Raster image on world map in ggplot

I want to fill certain values (pressure) continuously as gradient fill on a world map and I am writing the following code:
df = data.frame(phi)
names(df) = lat
df$lon= lon
mdata = melt(df, id=c("lon"))
names(mdata) = c("lon", "lat", "x")
mdata$x = as.numeric(mdata$x)
mdata$lon = as.numeric(mdata$lon)
mdata$lat = as.numeric(as.character(mdata$lat))
wr <- map_data("world")
# Prepare a map of World
wrmap <- ggplot(wr, aes(x = long, y = lat, group = group)) +
geom_polygon(fill = "white", colour = "black") +
geom_point(data=mdata, inherit.aes=FALSE, aes(x=lon, y=lat, colour=x), size=3, shape=4) +
scale_fill_gradient("Phi", limits=c(4500,6000)) +
theme_bw() +
coord_equal()
wrmap
Unfortunately the points are coming out discreet.
Any ideas how to fix this?
I am not exactly sure what you want because you didn't give us any data, but I made some guesses and did this:
library(ggplot2)
library(maps)
library(reshape2)
# Generate some fake data
lat <- seq(-90, 90, by = 5)
lon <- seq(-180, 180, by = 10)
phi <- 1500*tcrossprod( sin( pi*lat/180 ), cos( pi*lon/180 ))^ 2 + 4500
# above thanks to #NBAtrends for turning my two ugly for loops into this elegant statement
df = data.frame(phi)
names(df) = lat
df$lon = lon
mdata = melt(df, id = c("lon"))
names(mdata) = c("lon", "lat", "x")
mdata$x = as.numeric(mdata$x)
mdata$lon = as.numeric(mdata$lon)
mdata$lat = as.numeric(as.character(mdata$lat))
wr <- map_data("world")
# Prepare a map of World
wrmap <- ggplot(wr, aes(x = long, y = lat, group = group)) +
geom_polygon(fill = "white", colour = "black") +
geom_point(data=mdata, inherit.aes=FALSE,aes(x=lon, y=lat, color=x),size=3) +
scale_color_gradient("Phi", limits = c(4500, 6000)) +
theme_bw() +
coord_equal()
wrmap
Yielding this, which seems close to what you probably want:
This leads me to conclude that the problem is with your data. By comparing it to my fake data, I think you can probably figure out your problem.
Also I changed the "x" to a circle since you couldn't see it's color very well.

Controlling display of background map in ggmap for custom set of shapefiles

I'm working with a data set corresponding to the extract below:
# Data sourcing -----------------------------------------------------------
# Download an read US state shapefiles
tmp_shps <- tempfile(); tmp_dir <- tempdir()
download.file("http://www2.census.gov/geo/tiger/GENZ2014/shp/cb_2014_us_state_20m.zip",
tmp_shps)
unzip(tmp_shps, exdir = tmp_dir)
# Libs
require(rgdal); require(ggplot2)
# Read
us_shps <- readOGR(dsn = tmp_dir, layer = "cb_2014_us_state_20m")
# Prepare data set for ggplot2
us_shps_frt <- fortify(us_shps, region = "NAME")
From within that data set I subset a custom selection of shapefiles, like in the example below:
map_shps <- ggplot(data = us_shps_frt[grep("South", us_shps_frt$id),]) +
geom_polygon(aes(x = long, y = lat, group = group,
fill = id)) +
coord_equal() +
ggtitle("Odd Map") +
theme_map()
Given the odd selection of shapefiles above I would like to fit a background map that would neatly overlay with the maximum extent of the polygons. Initially I tried to achieve this in a following manner:
# Get box for the map
bbox <- make_bbox(lon = long, lat = lat,
data = us_shps_frt[grep("South", us_shps_frt$id),],
f = 0.5)
map_backgr <- get_map(bbox, maptype = "roadmap", zoom = 5,
source = "google", scale = 2, messaging = TRUE)
map_backgr <- ggmap(map_backgr, extent = "normal", maprange = FALSE)
and then generating the map:
map_backgr +
geom_polygon(data = us_shps_frt[grep("South", us_shps_frt$id),],
aes(x = long, y = lat, group = group,
fill = id)) +
coord_equal() +
ggtitle("Odd Map with Background") +
theme_map()
The produced graphic does not fit the polygons well:
I'm interested in adjusting the background map so it matches the polygons exactly. In particular I would like to crop/shorten the background by the red lines marked in the picture below:
Idea 1: Go with Stamen, they support oddly-shaped maps:
dat <- us_shps_frt[grep("South", us_shps_frt$id),]
ggmap(get_stamenmap(c(min(dat$long), min(dat$lat),
max(dat$long), max(dat$lat)),
zoom = 6)) +
geom_polygon(data = dat,
aes(x = long, y = lat, group = group,
fill = id)) +
ggtitle("Odd Map with Background")
Idea 2: Cut your Google Maps map:
dat <- us_shps_frt[grep("South", us_shps_frt$id),]
ggmap(get_map(c(min(dat$long), min(dat$lat), max(dat$long), max(dat$lat)))) +
geom_polygon(data = dat,
aes(x = long, y = lat, group = group,
fill = id)) +
ggtitle("Odd Map with Background") +
coord_map(xlim = c(min(dat$long), max(dat$long)),
ylim = c(min(dat$lat), max(dat$lat)))
But this one is still a bit off and I assume you need to play with the projection = "..." and parameters = "..." of coord_map().

Labeling center of map polygons in R ggplot

I am trying to label my polygons by using ggplot in R. I found a topic here on stackoverflow that I think is very close to what I want except with points.
Label points in geom_point
I found some methods online. Now I first need to find the central location of each shape and then I have to put these locations together with the name together. Then link this to the labeling function in geom_text()
ggplot centered names on a map
Since I have been trying for a long time now I decided to ask the question and hope that someone here can give me the final push to what I want. My plotting function:
region_of_interest.fort <- fortify(region_of_interest, region = "score")
region_of_interest.fort$id <- as.numeric(region_of_interest.fort$id)
region_of_interest.fort$id <- region_of_interest.fort$id
region_of_interest.fort1 <- fortify(region_of_interest, region = "GM_NAAM")
region_of_interest.fort1$id <- as.character(region_of_interest.fort1$id)
region_of_interest.fort1$id <- region_of_interest.fort1$id
idList <- unique(region_of_interest.fort1$id)
centroids.df <- as.data.frame(coordinates(region_of_interest))
names(centroids.df) <- c("Longitude", "Latitude")
randomMap.df <- data.frame(id = idList, shading = runif(length(idList)), centroids.df)
ggplot(data = region_of_interest.fort, aes(x = long, y = lat, fill = id, group = group)) +
geom_polygon() +
geom_text(centroids.df, aes(label = id, x = Longitude, y = Latitude)) +
scale_fill_gradient(high = "green", low = "red", guide = "colorbar") +
coord_equal() +
theme() +
ggtitle("Title")
It gives me the error: ggplot2 doesn't know how to deal with data of class uneval
My data
region_of_interest$GM_NAAM
[1] Groningen Haren Ooststellingwerf Assen Aa en Hunze Borger- Odoorn
[7] Noordenveld Westerveld Tynaarlo Midden-Drenthe
415 Levels: 's-Gravenhage 's-Hertogenbosch Aa en Hunze Aalburg Aalsmeer Aalten ... Zwolle
region_of_interest$score
[1] 10 -2 -1 2 -1 -4 -4 -5 0 0
Try something like this?
Get a data frame of the centroids of your polygons from the
original map object.
In the data frame you are plotting, ensure there are columns for
the ID you want to label, and the longitude and latitude of those
centroids.
Use geom_text in ggplot to add the labels.
Based on this example I read a world map, extracting the ISO3 IDs to use as my polygon labels, and make a data frame of countries' ID, population, and longitude and latitude of centroids. I then plot the population data on a world map and add labels at the centroids.
library(rgdal) # used to read world map data
library(rgeos) # to fortify without needing gpclib
library(maptools)
library(ggplot2)
library(scales) # for formatting ggplot scales with commas
# Data from http://thematicmapping.org/downloads/world_borders.php.
# Direct link: http://thematicmapping.org/downloads/TM_WORLD_BORDERS_SIMPL-0.3.zip
# Unpack and put the files in a dir 'data'
worldMap <- readOGR(dsn="data", layer="TM_WORLD_BORDERS_SIMPL-0.3")
# Change "data" to your path in the above!
worldMap.fort <- fortify(world.map, region = "ISO3")
# Fortifying a map makes the data frame ggplot uses to draw the map outlines.
# "region" or "id" identifies those polygons, and links them to your data.
# Look at head(worldMap#data) to see other choices for id.
# Your data frame needs a column with matching ids to set as the map_id aesthetic in ggplot.
idList <- worldMap#data$ISO3
# "coordinates" extracts centroids of the polygons, in the order listed at worldMap#data
centroids.df <- as.data.frame(coordinates(worldMap))
names(centroids.df) <- c("Longitude", "Latitude") #more sensible column names
# This shapefile contained population data, let's plot it.
popList <- worldMap#data$POP2005
pop.df <- data.frame(id = idList, population = popList, centroids.df)
ggplot(pop.df, aes(map_id = id)) + #"id" is col in your df, not in the map object
geom_map(aes(fill = population), colour= "grey", map = worldMap.fort) +
expand_limits(x = worldMap.fort$long, y = worldMap.fort$lat) +
scale_fill_gradient(high = "red", low = "white", guide = "colorbar", labels = comma) +
geom_text(aes(label = id, x = Longitude, y = Latitude)) + #add labels at centroids
coord_equal(xlim = c(-90,-30), ylim = c(-60, 20)) + #let's view South America
labs(x = "Longitude", y = "Latitude", title = "World Population") +
theme_bw()
Minor technical note: actually coordinates in the sp package doesn't quite find the centroid, but it should usually give a sensible location for a label. Use gCentroid in the rgeos package if you want to label at the true centroid in more complex situations like non-contiguous shapes.
The accepted answer here may work, but the actual question asked specifically notes that there is an error "ggplot2 doesn't know how to deal with data of class uneval."
The reason that it is giving you the error is because the inclusion of centroids.df needs to be a named variable (e.g. accompanied by "data=")
Currently:
ggplot(data = region_of_interest.fort, aes(x = long, y = lat, fill = id, group = group)) +
geom_polygon() +
geom_text(centroids.df, aes(label = id, x = Longitude, y = Latitude)) +
scale_fill_gradient(high = "green", low = "red", guide = "colorbar") +
coord_equal() +
theme() +
ggtitle("Title")
Should be (note: "data=centroids.df"):
ggplot(data = region_of_interest.fort, aes(x = long, y = lat, fill = id, group = group)) +
geom_polygon() +
geom_text(data=centroids.df, aes(label = id, x = Longitude, y = Latitude)) +
scale_fill_gradient(high = "green", low = "red", guide = "colorbar") +
coord_equal() +
theme() +
ggtitle("Title")
This issue was addressed here: How to deal with "data of class uneval" error from ggplot2?

Resources