Close polygon on ggmap (stat_contour) - r

I have recently started coding with R, so far it has been quite a journey with several obstacles on the road. Most of them I have been able to solve by searching the internet. However, now I am encountering a problem I am unable to fix. I found a sort of similair thread on stackoverflow, (How to fill in the contour fully using stat_contour), nevertheless it does not work in my situation, ggmap + ggplot seem unable to work together.
So, the problem is the following. I am studying whether the red light district in Amsterdam has an effect on local businesses. I do this by creating plot that shows business density in the city centre of Amsterdam. I have used this code to make it:
# Background map
geo <- geocode("Amsterdam", source="google")
lon <- geo$lon - .000
lat <- geo$lat + .000
map <- get_map(c(lon = lon, lat = lat), zoom=14,maptype = "satellite", color="color")
p <- ggmap(map) + theme(legend.position = c(1, 1), legend.justification = c(1,1)) +
xlab("Longitude") + ylab("Latitude")
# Map boundaries
#xmin = 4.86774509503174
#xmax = 4.92267673565674
#ymin = 52.3534171572766
#ymax = 52.386956071714
# RLD Map (so it can be read by ggplot2)
rldmap <- fortify(rld)
rld2map <- fortify(rld2)
natmap <- fortify(nat)
# Ticks
mid <- 250
mi <- 0
ma <- 500
r <- (ma-mi)/5
breaks = seq(mi,ma,r)
# Density
ncells <- 150
dens2000 <- kde2d(bedrijven2000$LONG, bedrijven2000$LAT, n = ncells)
densdf2000 <- data.frame(expand.grid(x = dens2000$x, y = dens2000$y), z = as.vector(dens2000$z))
densmap2000 <- p + geom_point(aes(x = x, y = y), data = coords2000, alpha = .5, size = 1) +
stat_contour(aes(x,y,z=z,fill = ..level..), data=densdf2000,geom="polygon", alpha=.3, inherit.aes = F) +
scale_fill_gradientn(name="density", breaks = breaks, colours=rev(brewer.pal(7,"Spectral"))) +
geom_polygon(aes(x=long, y=lat, group=group), fill='grey', size=.2,color='green', data=rldmap, alpha=0) +
geom_polygon(aes(x=long, y=lat, group=group), fill='grey', size=.2,color='green', data=rld2map, alpha=0) +
geom_polygon(aes(x=long, y=lat, group=group), fill='grey', size=.2,color='green', data=natmap, alpha=0) +
geom_point(aes(x = x, y = y), data = coords,color = 'yellow',alpha = 1, size = 1, shape=10) +
annotate('text', x=4.892, y=52.374, label = "Amsterdam", col="white") +
ggtitle("Business Density in Amsterdam year=2000")
plot(densmap2000)
Using this code provides the following output:
output density plot Amsterdam
The problem here is that the lines of the polygons that show the density stop when they are close to the border of the plot, this gives a disturbing image.
Therefore my question is, how can I make the polygons forget about the borders of the graph and make them continuous?

Managed to answer the question myself in the end, thanks to this thread: Truncated Density Polygons with ggmap
the answer lies in two parts:
1, edit extend and maprange in background map
ggmap(map, extent="normal", maprange=FALSE)
2, edit in code for plot, add:
coord_cartesian(xlim=c(min(4.86774509503174),max(4.92267673565674)),
ylim=c(min(52.3534171572766),max(52.386956071714))) +

Related

Is there a way to make this map more aesthetically pleasing by turning it into a choropleth?

Using this dataset: https://www.kaggle.com/datasets/syuzai/perth-house-prices. Is there a way of prettying it up (besides changing the colour scale) by turning it into a choropleth? Each individual point represents the price of a single house; the original data does organise the house prices by suburb level but the ozmaps package only gives boundaries up to LGA/district level.
library(ozmaps)
library(sf)
library(ggplot2)
ozmaps <- ozmaps::ozmap_states
p<- ggplot(ozmaps) +
geom_sf() +
geom_point(data = PerthReg2005, aes(x = LONGITUDE, y = LATITUDE, colour = PRICE),
size = 1, shape = 23,) +
coord_sf(xlim = c(115.5827,116.3432), ylim = c(-31.45745,-32.47298))
p + scale_colour_gradientn(colours = terrain.colors(10))

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?

display data on a map

I need to plot my variable Omega as a heat map on the Pacific Ocean.
I have the coordinates and the Omega values but ggplot would only plot a world map while my omega appears as a separate figure (See image attached)
This is my data where y and x are Lat and Longs for my sites
Country Omega y x
1 Guam 3.28 144.7822 13.66660
2 Guam 3.28 144.7605 13.62500
This is the code I am using
map.world <- map_data(map = "world")
gg <- ggplot()
gg <- gg + theme(legend.position = "none")
gg <- gg +
geom_map(data = map.world, map = map.world,
aes(map_id = region, x = long, y = lat),
fill = "white", colour = "black", size = 0.25) +
theme_bw()
omega <- read.csv("map.csv", header = T)
head(omega)
g <- gg +
geom_polygon() +
geom_point(data = omega, aes(y = y, x = x, color = Omega)) +
theme_minimal()
I need to plot my Omega in my study sites and generate a heat map. Please any help would be very appreciated. Thank you very much
You might want to have a look at the leaflet package, it’s easier to use and better
library(leaflet)
df <- data.frame(Country=c("Guam","Guam"),
Omega=c(3.28,3.28),
y=c(144.7822, 144.7605),
x=c(13.6660, 13.6250))
m <- leaflet(data=df)
content <- paste("Omega Value:",df$Omega)
m %>% addCircles(lng=~y, lat=~x, radius=df$Omega, popup=content) %>%
setView(lng=144.793732, lat=13.444304, zoom=10)

Points changing sizes on ggplot geom_point and no legend?

Okay so here is my code for a base map:
gg <- ggmap(Peru) +
geom_map(data = peru.coast, map = peru.coast, aes(x = long, y = lat, map_id = region),
fill="gray", color="black") +
xlim(-86, -70) +
ylim(-20, -4) +
labs(x = "Longitude", y = "Latitude") +
coord_map()
I then add in towns I wish to name manually (wasn't sure how to do it using google maps as I only wanted these 4)
gg <- gg + geom_point(aes(x=-78.981885, y=-8.229354, size=3)) +
annotate("text", label='Salaverry', size=4, x=-77.2, y=-8.229354) +
geom_point(aes(x=-71.345838, y=-17.644347, size=3)) +
annotate("text", x=-70.545838, y=-17.644347, label = 'Ilo', size=4) +
geom_point(aes(x=-77.142375, y=-12.047544, size=3)) +
annotate("text", x=-75.9, y=-12.047544, label = 'Callao', size=4) +
geom_point(aes(x=-78.610677, y=-9.074166, size=3)) +
annotate("text", x=-76.9, y=-9.074166, label = 'Chimbote', size=4)
gg <- gg + guides(size=FALSE) #this removes the legend with the black dot and '3' on it
gg
I get this lovely map:
I then use this dataset to add datapoints, and I wish to make the points bigger or smaller according to 'n' abundance
Trip_Set sex Set.Lon Set.Lat n
119_1 hembra -81.09390 -9.32338 2
119_7 hembra -81.03117 -9.09622 1
161_3 macho -83.76533 -9.74533 5
193_8 hembra -81.00888 -9.00950 7
255_5 macho -80.14992 -8.64592 1
271_6 hembra -72.20233 -18.05117 6
271_6 macho -72.20233 -18.05117 7
328_7 hembra -78.66667 -12.91700 2
403_3 hembra -80.03037 -10.03900 1
428_2 hembra -83.01305 -8.74883 2
655_4 hembra -71.58363 -18.24882 1
using this code:
ggAB <- gg + geom_point(data=dframe4, aes(Set.Lon, Set.Lat, colour='red', size=n))
ggAB <- ggAB + theme(legend.title = element_text(colour="black", size=12, face="bold"))
ggAB <- ggAB + guides(colour=FALSE) #This removes the legend for the red colour
ggAB <- ggAB + scale_size(name='Sharks per line', range = c(5,9))
ggAB <- ggAB + theme(legend.key=element_rect(fill = NA)) #This removes the boxes around the points
ggAB
However, when I do this... I get this:
The datapoints are plotted great (phew!), but why does it make the points bigger for my town names? I can't seem to get it to just keep the abundance for my 'n' number datapoints... It also doesn't put an automatic legend on (as ggplot usually does), even when I try and put one in manually using the scale_discrete function.
I thought it might be something to do with the fact that I use gg + guides(size=FALSE) in the first part, but even when taking that out it doesn't work, but adds in an annoying legend for my town datapoints.
Any ideas?
The problem is that in the code where you add the towns, you have put the size inside the aes. Therefore it also gets transformed when you call scale_size(name='Sharks per line', range = c(5,9)). Just use size outside the aes:
gg <- gg + geom_point(aes(x=-78.981885, y=-8.229354), size=3) +
annotate("text", label='Salaverry', size=4, x=-77.2, y=-8.229354) +
geom_point(aes(x=-71.345838, y=-17.644347), size=3) +
annotate("text", x=-70.545838, y=-17.644347, label = 'Ilo', size=4) +
geom_point(aes(x=-77.142375, y=-12.047544), size=3) +
annotate("text", x=-75.9, y=-12.047544, label = 'Callao', size=4) +
geom_point(aes(x=-78.610677, y=-9.074166), size=3) +
annotate("text", x=-76.9, y=-9.074166, label = 'Chimbote', size=4)
In addition to #shadow's answer, I'd like to leave the following for the OP as supplementary information. This comes from the chat with the OP. If you want to avoid using annotate, you can use geocode in the ggmap package. Here, I added some from my answer to the previous question of the OP, and I combined/modified the OP's code. One change is that I used alpha so that you can see red/pink points in the ocean. One note is that the positions of the city names are not perfect; the further you go down south in the map, the more you see gaps between points and city names. This could be due to something to do with map projection. According to Wiki, googlemap is using something close to marcator, but not exact the same. This could be the reason. Some GIS experts here would be able to provide more information.
library(ggmap)
library(mapdata)
library(ggplot2)
# Get Peru map
Peru <- get_map(location = "Peru", zoom = 5, maptype="satellite")
# This is the layer I wish to put over the top
coast_map <- fortify(map("worldHires", fill = TRUE, plot = FALSE))
# Subset data for Peru
peru.coast <- subset(coast_map, region == "Peru")
### Get lon and lat using geocode() in the ggmap package and crate a data frame
cities <- c("Salaverry", "Chimbote", "Callao", "Ilo")
locations <- geocode(cities)
locations$city <- cities
locations2 <- transform(locations, lon2 = lon + 1.1) # This is for text position
ggmap(Peru) +
geom_map(data = peru.coast, map = peru.coast, aes(x = long, y = lat, map_id = region),
fill="gray", color="black") +
geom_point(data = locations2, aes(x = lon, y = lat, color = city), size = 4) +
geom_text(data = locations2, aes(x = lon2, y = lat, label = city), size = 3) +
scale_color_manual(values = rep(c("black"), times = 4)) +
geom_point(data = newdata, aes(Set.Lon, Set.Lat, size = n), colour = "red", alpha = 0.5) +
scale_size(name = "Sharks per line", range = c(5,9)) +
xlim(-86, -70) +
ylim(-20, -4) +
labs(x = "Longitude", y = "Latitude") +
coord_map("mercator") +
guides(colour=FALSE) +
theme(legend.key=element_rect(fill = NA))

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