Related
I have a shapefile with 7 regions.
I have an excel file with data about reptiles in these 7 regions.
I merged this shapefile with excel.
Using ggplot I tried to generate facet_wrap() from nome_popular, however the rest of the polygon parts were omitted in each facet created.
My tentative code
shapefile: https://drive.google.com/file/d/1I1m9lBX69zjsdGBg2zfpii5H4VFYE1_0/view?usp=sharing
excel:https://docs.google.com/spreadsheets/d/1eKQWWCAalehTTrUuqUlMPQnSTEZxF--g/edit?usp=sharing&ouid=118442515534677263769&rtpof=true&sd=true
# load data.frame
serpentes <- read_excel("E:/22-serpentes_cg/R/serpentes_cg_finall.xlsx")
# filer data.frame
total_especies <- serpentes %>%
rename(regiao_cg = REGIAO_CG) %>%
group_by(
especie, nome_popular,
regiao_cg
) %>%
summarise(Total_esp = sum(quant))
# load shapefile
regiao <- sf::st_read("E:/22-serpentes_cg/geo/regioes_urbanas.shp") %>%
rename(regiao_cg = REGIAO_CG)
# join shapefile and excel
total_especies_shp <- dplyr::left_join(regiao, total_especies, by = "regiao_cg")
# map facet_warp
p_total_especies_shp <- ggplot(
na.omit(total_especies_shp),
aes(fill = factor(Total_esp))
) +
geom_sf() +
scale_fill_brewer(
palette = "Spectral", na.value = "grey", direction = -1,
"Total de\nSepertens Regatadas"
) +
facet_wrap(~nome_popular)
p_total_especies_shp
output incomplete
OBS EDIT
I tried #stefan's answer which partly worked, but generated a facet called "NA" bad.
new code:
p_total_especies_shp <- ggplot(total_especies_shp)+
geom_sf(data=regiao)+
geom_sf(aes(fill=factor(Total_esp)))+
scale_fill_brewer(
palette = "Spectral", na.value = "grey", direction = -1,
"Total de\nSepertens Regatadas")+
facet_wrap(~nome_popular)
p_total_especies_shp
The issue is that with faceting the data is splitted in groups and only the polygons contained in the splitted data will show up.
If you want all regions to be shown in each facet then one option would be to add a base map via second geom_sf layer. In your case + geom_sf(regiao) + geom_sf() should do the job.
As an example I make use of the default example from ?geom_sf:
library(ggplot2)
set.seed(42)
nc <- sf::st_read(system.file("shape/nc.shp", package = "sf"), quiet = TRUE)
base <- nc
nc$facet <- sample(c("a", "b", "c", "d"), size = nrow(nc), replace = TRUE)
ggplot(nc) +
geom_sf(data = base) +
geom_sf(aes(fill = AREA)) +
facet_wrap(~facet)
Working on #stefan answer, if you want to get rid of the NA panel, you need to provide the data in the second geom with the na.omit, leaving the ggplot call empty:
p_total_especies_shp <- ggplot() +
geom_sf(data = regiao) +
geom_sf(aes(fill = factor(Total_esp)), data = na.omit(total_especies_shp)) +
scale_fill_brewer(
palette = "Spectral", na.value = "grey", direction = -1,
"Total de\nSepertens Regatadas"
) +
facet_wrap(~nome_popular, drop = TRUE)
p_total_especies_shp
Which gives the result you want:
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?
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 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?
I am trying to add state abbreviations to a US map generated using ggplot2 and having some difficulties with it. I believe the "fill = " option is causing it, but I am not sure.
Below I provide the code I am using. Initially, I generate the map the way I want except for the state names. Next, I try to overlay state abbreviations on the same map.
Unfortunately it is not working out for me. If I comment out "fill = " option from the first map, I can generate a map with state abbreviations. But that map does not show what I intend to show. I have tried several ways. I am just leaving one option in the code for the moment.
To add the state abbreviations, I am following some of the suggestions I have read in this forum. In particular, I am trying to follow the advice from a discussion titled "ggplot centered names on a map" dated February 25, 2012.
I would appreciate any help on how I can add/overlay the state abbreviations to the first map.
# Master US location data
states <- map_data("state")
# Read in the data
rate <- read.csv("~/R/HealthCare/Data/Test_data.csv")
names(rate) <- tolower(names(rate))
rate$numer <- as.factor(rate$numer)
rate$region <- tolower(rate$statename)
# Create data for US mapping
tomap <- merge(states, rate, sort = FALSE, by = "region")
tomap <- tomap[order(tomap$order), ]
## US Map
# 1. Target Map (w/o state abbr)
p <- qplot(long, lat, data = tomap,
group = group,
fill = numer,
geom = "polygon")
p + scale_fill_brewer(palette = "Greens",
guide = guide_legend(reverse = TRUE),
labels = c("1st cat", "2nd cat",
"3rd cat", "4th cat"))
# 2. Add State Abbreviations to Target Map
stannote <- aggregate(cbind(long, lat, group, numer) ~ stateabbr, data = tomap,
FUN=function(x)mean(range(x)))
q <- qplot(long, lat, data = tomap,
group = group,
#fill = numer,
fill = "red", #testing
geom = "polygon") +
geom_text(data=stannote, aes(long, lat, label = stateabbr), color = "blue", size=3) +
coord_map()
q
The sample data file looks like the following –
StateName,StateAbbr,Numer
Alabama,AL,0
Alaska,AK,0
Arizona,AZ,0
Arkansas,AR,0
California,CA,0
Colorado,CO,0
Connecticut,CT,0
Delaware,DE,0
District of Columbia,DC,1
Florida,FL,0
Georgia,GA,0
Hawaii,HI,0
Idaho,ID,1
Illinois,IL,0
Indiana,IN,0
Iowa,IA,1
Kansas,KS,0
Kentucky,KY,1
Louisiana,LA,1
Maine,ME,2
Maryland,MD,0
Massachusetts,MA,2
Michigan,MI,0
Minnesota,MN,1
Mississippi,MS,0
Missouri,MO,0
Montana,MT,0
Nebraska,NE,0
Nevada,NV,1
New Hampshire,NH,1
New Jersey,NJ,2
New Mexico,NM,1
New York,NY,3
North Carolina,NC,0
North Dakota,ND,1
Ohio,OH,0
Oklahoma,OK,0
Oregon,OR,2
Pennsylvania,PA,0
Rhode Island,RI,0
South Carolina,SC,0
South Dakota,SD,1
Tennessee,TN,0
Texas,TX,0
Utah,UT,1
Vermont,VT,2
Virginia,VA,0
Washington,WA,2
West Virginia,WV,0
Wisconsin,WI,0
Wyoming,WY,0
As often happens to me with R, it turns out the error message was telling you exactly what was happening (it just takes a while to figure it out). Your numer variable in your second dataset stannote is continuous (check the structure with str(stannote) to see this). So you can just change that variable to a factor. Watch out, though: when you used cbind in aggregate I think you forced the factor to be turned into a numeric variable and so numer in stannote goes from 1-4 instead of 0-3.
Option 1:
stannote$numer = factor(stannote$numer, labels = c(0, 1, 2, 3))
qplot(long, lat, data = tomap,
group = group,
fill = numer, #testing
geom = "polygon") +
geom_text(data=stannote, aes(long, lat, label = stateabbr),
color = "blue", size=3) + scale_fill_brewer(palette = "Greens")
Alternatively, you could remove the fill aesthetic that you set for the overall plot from the call to geom_text using fill = NULL. You don't actually need fill for the text, just for the polygons. This is a situation where if you were using ggplot instead of qplot you might just set the fill aesthetic for geom_polygon.
Option 2:
stannote$numer = as.numeric(stannote$numer)
qplot(long, lat, data = tomap,
group = group,
fill = numer, #testing
geom = "polygon") +
geom_text(data=stannote, aes(long, lat, label = stateabbr, fill = NULL),
color = "blue", size=3) + scale_fill_brewer(palette = "Greens")