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?
Related
I have a shapefile here: https://login.filesanywhere.com/fs/v.aspx?v=8c6c63865a6574bcaa69
I have a shapefile of California red legged frog that I am overlaying on top of California, however, the range of these frogs extends outside of California and going into Mexico. I only want the frog data from California, how can I trim data extending into Mexico? I tried to use subset to separate the 'ORIGIN' but it doesn't seem to have any effect. Thanks for any help beforehand..
library(rgdal)
library(tidyverse)
ranas <- readOGR(dsn = ".", layer = "data_0")
names(ranas)
# Coerce into a dataframe
ranas4 <- fortify(ranas)
head(ranas4)
cali_map <- map_data("state",region="california")
counties <- map_data("county",region="California")
head(counties)
windows(w=9)
ggplot(cali_map, aes(x = long, y = lat, group = group)) +
geom_polygon() +
geom_polygon(data = ranas4, fill = "green")
ggplot(cali_map, aes(x = long, y = lat, group = group)) +
geom_polygon(fill = "cornsilk4", col = "cornsilk") +
geom_polygon(data=counties,color="black",fill="lightgoldenrod") +
geom_polygon(data = ranas4, fill = "green", alpha = 0.5) +
theme_void() +
theme(panel.background = element_rect(fill = "cornsilk")) +
coord_map("albers",lat=90,lat1=80)
# Tried to trim data outside California (Mexico data) with no success.
#I tried:
ranas2 <- subset(ranas,ORIGIN !=1)
but it doesn't have any effect or subsets anything.
Subsetting your spatial dataframe won't be of much use, because neither of its features (rows) is entirely within California:
## plot features by origin:
library(ggplot2)
library(sf)
my_shp <- read_sf(dsn = "path_to_shp_directory")
my_shp %>%
ggplot() +
geom_sf() +
facet_wrap(~ ORIGIN)
You can still crop (clip) a feature with California's boundaries ...:
## make sure both geometries have the same CRS,
## if necessary, by st_transform(your_epsg_code)
my_shp_cropped <- st_crop(my_shp, cali_map)
... but note that won't recalculate the underlying frog data (e.g. frog count in California only).
I'm trying to use geom_path and geom_text to create a labeled map, but it is not going well. I can use each geom_path and geom_text separately, but I can't seem to get them to work together. I think it has something to do with geom_polygon, but I'm not sure what.
Here is how I prepared my shapefile for mapping:
meck.hiv <- as(meck.hiv, "Spatial")
meck.hiv#data$seq_id <- seq(1:nrow(meck.hiv#data)) #create unique id for each polygon
meck.hiv#data$id <- rownames(meck.hiv#data)
meck.hivdf <- fortify(meck.hiv) #fortify the data
zipcodedf <- merge(meck.hivdf, meck.hiv#data,
by = "id")# merge the "fortified" data with the data from our spatial object
cnames <- aggregate(cbind(long, lat) ~ zip, data=zipcodedf, FUN=function(x)mean(range(x))) #get the names of our zipcode (and center the coordinates for labels)
With this, I was able to get the following maps:
With labels, no paths:
p2 <- ggplot(data = zipcodedf, aes(x = long, y = lat)) +
geom_polygon(aes(group=group, fill=hispanic.dis)) +
geom_text(data=cnames, aes(long, lat, label = zip), size=3, fontface='bold', color="black")+ #This put in zip code names
scale_fill_brewer(breaks=c(1, 2, 3, 4, 5, 6, 7), labels=c("<5", "5-10", "11-15", "16-20", "21-25", "26-30", "31+"), palette="Reds",
na.value="darkgrey") +
coord_equal() +
theme(panel.background= element_rect(color="black")) +
theme(axis.title = element_blank(), axis.text = element_blank()) +
labs(title = "Hispanic Population by Zip Code", fill="Hispanic Population (% of Total)")
Resulting map with labels but no path
Paths, but no labels:
p3 <- ggplot(data = zipcodedf, aes(x = long, y = lat, group = group, fill = hispanic.dis)) +
geom_polygon() +
geom_path(color = "black", size = 0.2)+ #Oddly, use of geom_path with the above leads to weird stuff, but we can customize map lines without labels here
scale_fill_brewer(breaks=c(1, 2, 3, 4, 5, 6, 7), labels=c("<5", "5-10", "11-15", "16-20", "21-25", "26-30", "31+"), palette="Reds",
na.value="darkgrey") +
coord_equal() +
theme(panel.background=element_blank())+
theme(panel.background= element_rect(color="black")) +
theme(axis.title = element_blank(), axis.text = element_blank()) +
labs(title = "Hispanic Population by Zip Code", fill="Hispanic Population(% of Total)")
Resulting path with paths but no labels
Trying to combine
p4 <- ggplot(data = zipcodedf, aes(x = long, y = lat)) +
geom_polygon(aes(group=group, fill=hispanic.dis)) +
geom_text(data=cnames, aes(long, lat, label = zip), size=3, fontface='bold', color="black")+
geom_path(color = "black", size = 0.2)+ #Oddly, use of geom_path with the above leads to weird stuff, but we can customize map lines without labels here
scale_fill_brewer(breaks=c(1, 2, 3, 4, 5, 6, 7), labels=c("<5", "5-10", "11-15", "16-20", "21-25", "26-30", "31+"), palette="Reds",
na.value="darkgrey") +
coord_equal() +
theme(panel.background=element_blank())+
theme(panel.background= element_rect(color="black")) +
theme(axis.title = element_blank(), axis.text = element_blank()) +
labs(title = "Hispanic Population by Zip Code", fill="Hispanic Population(% of Total)")
Resulting screwed up plot with paths and labels
My trouble-shooting suggests that there's something about how geom_path is interacting with geom_polygon combined with ggplot(), but if I move all the instructions into geom_polygon, path doesn't show up at all (although a plot will generate), and if I move all the instructions into ggplot(), I get an error: "Error in FUN(X[[i]], ...): object 'group' not found" (below).
p5 <- ggplot(data = zipcodedf, aes(x = long, y = lat, group = group, fill = hispanic.dis)) +
geom_polygon() +
geom_path(color = "black", size = 0.2)+
geom_text(data=cnames, mapping=aes(x=long, y=lat))+#Oddly, use of geom_path with the above leads to weird stuff, but we can customize map lines without labels here
scale_fill_brewer(breaks=c(1, 2, 3, 4, 5, 6, 7), labels=c("<5", "5-10", "11-15", "16-20", "21-25", "26-30", "31+"), palette="Reds",
na.value="darkgrey") +
coord_equal() +
theme(panel.background=element_blank())+
theme(panel.background= element_rect(color="black")) +
theme(axis.title = element_blank(), axis.text = element_blank()) +
labs(title = "Hispanic Population by Zip Code", fill="Hispanic Population(% of Total)")
Any help is appreciated. Please let me know if I need to provide more information on anything.
{ggplot2}'s layering and inheritance can be confusing at times. I hope the following helps. Also check out whether you really want an "additional" geom_path() layer. It feels like you want to depict/highlight the county boundaries. Please also note the use of color for setting the boundary(line) color for a layer in the example.
I have to emulate your problem, as you did not provide a reproducible example. The initial code is to get me the map data for North Carolina. I construct a cnames dataframe for the county names. You should be able to apply this to your zip-code problem at the county level ... :)
library(dplyr)
library(ggplot)
library(maps) # helper package to get some map data
library(mapdata) # helper for some map data
counties <- map_data("county") %>% filter(region == "north carolina")
head(counties)
yields a data frame
long lat group order region subregion
1 -79.53800 35.84424 1857 54915 north carolina alamance
2 -79.54372 35.89008 1857 54916 north carolina alamance
3 -79.53800 35.98175 1857 54917 north carolina alamance
4 -79.52081 36.23385 1857 54918 north carolina alamance
5 -79.26298 36.23385 1857 54919 north carolina alamance
6 -79.27444 35.90726 1857 54920 north carolina alamance
Plotting the counties only (note: this would be your zip-code level).
To explain the principle of layer inheritance, I "set" all parameters in the layer call (i.e. geom_polygon()):
ggplot() +
geom_polygon(data = counties
, aes(x = long, y = lat, group = group) # aesthetic mapping
, color = "white" # fixed value for "line"
, fill = "lightblue") # fixed value for "fill"
If you now would add the geom_path() layer without giving it aesthetics, the plot will not change. Check that I set the color to blue and the linesize to 2 for demo purposes.
ggplot() +
geom_polygon(data = counties, aes(x = long, y = lat, group = group), colour = "white", fill = "lightblue") +
# ---------------- adding a layer with no aesthetics -----------
geom_path(color = "blue", size = 2) # ... no joy!
If you now move the data and aesthetics to ggplot() "base"-layer, also path will inherit the aesthetics. In this case path will draw the "outlines" of the of the grouped lat/lon positions. The layer order and color/size of geom_path() will "overwrite" the white coloured polygon lines.
ggplot(data = counties, aes(x = long, y = lat, group = group)) +
geom_polygon( colour = "white", fill = "lightblue") +
#------------ path layer with inherited "polygon" grouping
geom_path(color = "blue", size = 2)
Next let's create the (zipcodes :) ) aka text labels by averaging the lat/lon values for the different polygon segment points.
cnames <- counties %>%
group_by(subregion) %>%
summarise(long = mean(long), lat = mean(lat) # averaging for "mid"-point
)
> cnames
# A tibble: 100 x 3
subregion long lat
<chr> <dbl> <dbl>
1 alamance -79.4 36.0
2 alexander -81.2 35.9
3 alleghany -81.1 36.5
Now add a geom_text() layer to show the (zip codes) aka subregion names.
ggplot(data = counties, aes(x = long, y = lat, group = group)) +
geom_polygon( colour = "white", fill = "lightblue") +
geom_path(color = "blue", size = 2) +
# --------------- adding a geom_text() layer
geom_text(data = cnames, aes(x = long, y = lat), color = "green")
## ------- uuummmppfff throws an error
Error in FUN(X[[i]], ...) : object 'group' not found
This throws an error. So why is that? Implicitly the group aesthetic in the ggplot() call is understood by geom_polygon() and geom_path() ... however geom_text() has issues with.
Moving the group aesthetics to the polygon layer ...
ggplot(data = counties, aes(x = long, y = lat)) +
geom_polygon( aes(group=group), colour = "white", fill = "lightblue") +
geom_path(color = "blue", size = 2) +
geom_text(data = cnames, aes(x = long, y = lat, label = "subregion"), color = "green")
does the trick but corrupts the geom_path() layer.
What happens here is that the data points (i.e. lat/lon) are no longer grouped, and ggplot connects the end points in the order they appear in the counties data frame. These are the jig-jag lines you see across your plot.
Accordingly, you would need to put another aes(group=group) for the geom_path layer! ... assuming you really want the path for the outlines.
ggplot(data = counties, aes(x = long, y = lat)) +
geom_polygon( aes(group=group), colour = "white", fill = "lightblue") +
geom_path(aes(group=group), color = "blue", size = 2) +
geom_text(data = cnames, aes(x = long, y = lat, label = "subregion"), color = "green")
Obviously the color = "white" is overwritten by the geom_path() call. You may skip one or the other.
As a rule of thumb, ggplot works well with "long" data tables. The moment you add a 2nd (or more other data objects) make sure to track which aesthetics are required and/or inherited from one layer to the other. In your original example, you could move the geom_path() upwards to have the group = group aesthetics from the geom_polygon() call.
In case of doubt, always populate the data = ... and aes() for each layer before combining (and inheriting) parameters across layers.
Good luck!
I am trying to plot new locations opened over each month on a map cumulatively. I am able to create an animation with new locations each month, but not cumulatively. In other words, I want to see the new locations add to the existing ones.
Here is the sample data
DF <- data.frame("latitude" = c(42.29813,41.83280,41.83280,30.24354),
"longitude" =c(-71.23154,-72.72642,-72.72642,-81.62098),
"month" = c(1,2,3,4))
This is what I have tried
usa <- ggplot() +
borders("usa", colour = "gray85", fill = "gray80") +
theme_map()
map <- usa +
geom_point(aes(x = longitude, y = latitude, cumulative=TRUE,
frame=month,stat = 'identity' ),data = DF )
map
# Generate the Visual and a HTML output
ggp <- ggplotly(map)%>%
animation_opts(transition = 0)
ggp
The output does not show locations cumulatively. I want to see all four locations in the end basically.
If you use gganimate you can include transition_states to animate your points. For cumulative addition of points, use shadow_mark to include data behind the current frame.
library(ggthemes)
library(gganimate)
library(ggplot2)
DF <- data.frame("latitude" = c(42.29813,41.83280,41.83280,30.24354),
"longitude" =c(-71.23154,-72.72642,-72.72642,-81.62098),
"month" = c(1,2,3,4))
usa <- ggplot() +
borders("usa", colour = "gray85", fill = "gray80") +
theme_map()
map <- usa +
geom_point(aes(x = longitude, y = latitude), color = "black", data = DF) +
transition_states(month, transition_length = 0, state_length = 1) +
shadow_mark()
map
Edit: To save the animation as a .gif, use anim_save.
anim_save("mapanim.gif", map)
In addition, if you want to change the width/height of the final animation, you can specify, for example:
animate(map, height = 400, width = 600)
I have been provided with some customer data in Latitude, Longitude, and Counts format. All the data I need to create a ggplot heatmap is present, but I do not know how to put it into the format ggplot requires.
I am trying to aggregate the data by total counts within 0.01 Lat and 0.01 Lon blocks (typical heatmap), and I instinctively thought "tapply". This creates a nice summary by block size, as desired, but the format is wrong. Furthermore, I would really like to have empty Lat or Lon block values be included as zeroes, even if there is nothing there... otherwise the heatmap ends up looking streaky and odd.
I have created a subset of my data for your reference in the code below:
# m is the matrix of data provided
m = matrix(c(44.9591051,44.984884,44.984884,44.9811399,
44.9969096,44.990894,44.9797023,44.983334,
-93.3120017,-93.297668,-93.297668,-93.2993524,
-93.2924484,-93.282462,-93.2738911,-93.26667,
69,147,137,22,68,198,35,138), nrow=8, ncol=3)
colnames(m) <- c("Lat", "Lon", "Count")
m <- as.data.frame(m)
s = as.data.frame((tapply(m$Count, list(round(m$Lon,2), round(m$Lat,2)), sum)))
s[is.na(s)] <- 0
# Data frame "s" has all the data, but not exactly in the format desired...
# First, it has a column for each latitude, instead of one column for Lon
# and one for Lat, and second, it needs to have 0 as the entry data for
# Lat / Lon pairs that have no other data. As it is, there are only zeroes
# when one of the other entries has a Lat or Lon that matches... if there
# are no entries for a particular Lat or Lon value, then nothing at all is
# reported.
desired.format = matrix(c(44.96,44.96,44.96,44.96,44.96,
44.97,44.97,44.97,44.97,44.97,44.98,44.98,44.98,
44.98,44.98,44.99,44.99,44.99,44.99,44.99,45,45,
45,45,45,-93.31,-93.3,-93.29,-93.28,-93.27,-93.31,
-93.3,-93.29,-93.28,-93.27,-93.31,-93.3,-93.29,
-93.28,-93.27,-93.31,-93.3,-93.29,-93.28,-93.27,
-93.31,-93.3,-93.29,-93.28,-93.27,69,0,0,0,0,0,0,
0,0,0,0,306,0,0,173,0,0,0,198,0,0,0,68,0,0),
nrow=25, ncol=3)
colnames(desired.format) <- c("Lat", "Lon", "Count")
desired.format <- as.data.frame(desired.format)
minneapolis = get_map(location = "minneapolis, mn", zoom = 12)
ggmap(minneapolis) + geom_tile(data = desired.format, aes(x = Lon, y = Lat, alpha = Count), fill="red")
Here is a stab with geom_hex and stat_density2d. The idea of making bins by truncating coordinates makes me a bit uneasy.
What you have is count data, with lat/longs given, which means ideally you would need a weight parameter, but that is as far as I know not implemented with geom_hex. Instead, we hack it by repeating rows per the count variable, similar to the approach here.
## hack job to repeat records to full count
m<-as.data.frame(m)
m_long <- with(m, m[rep(1:nrow(m), Count),])
## stat_density2d
ggplot(m_long, aes(Lat, Lon)) +
stat_density2d(aes(alpha=..level.., fill=..level..), size=2,
bins=10, geom=c("polygon","contour")) +
scale_fill_gradient(low = "blue", high = "red") +
geom_density2d(colour="black", bins=10) +
geom_point(data = m_long)
## geom_hex alternative
bins=6
ggplot(m_long, aes(Lat, Lon)) +
geom_hex(bins=bins)+
coord_equal(ratio = 1/1)+
scale_fill_gradient(low = "blue", high = "red") +
geom_point(data = m_long,position = "jitter")+
stat_binhex(aes(label=..count..,size=..count..*.5), size=3.5,geom="text", bins=bins, colour="white")
These, respectively, produce the following:
And the binned version:
EDIT:
With basemap:
map +
stat_density2d(data = m_long, aes(x = Lon, y = Lat,
alpha=..level.., fill=..level..),
size=2,
bins=10,
geom=c("polygon","contour"),
inherit.aes=FALSE) +
scale_fill_gradient(low = "blue", high = "red") +
geom_density2d(data = m_long, aes(x = Lon, y=Lat),
colour="black", bins=10,inherit.aes=FALSE) +
geom_point(data = m_long, aes(x = Lon, y=Lat),inherit.aes=FALSE)
## and the hexbin map...
map + #ggplot(m_long, aes(Lat, Lon)) +
geom_hex(bins=bins,data = m_long, aes(x = Lon, y = Lat),alpha=.5,
inherit.aes=FALSE) +
geom_point(data = m_long, aes(x = Lon, y=Lat),
inherit.aes=FALSE,position = "jitter")+
scale_fill_gradient(low = "blue", high = "red")
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?