I have a map with some points across it that were created with geom_point. They are in the exact location and color I need them to be, but I am trying to change the shape to a silhouette I imported from phylopic. Here is some sample data for the code
#Dataframe for the points
individual_dets = data.frame(longitude= seq(-64.5,-62.4,0.1),
latitude= seq(42.7,44.8,0.1),
year = sample(c(2016, 2017, 2018), 22, replace = T),
Zone = sample(c(1:4), 22, replace = T),
month = sample(month.abb, 22, replace = T))
Below is the code for my imported phylopic silhouette, and my code for the map with the points on it
library(rphylopic)
library(RCurl)
library(png)
library(mapdata)
#Import phylopic
rayurl = "http://phylopic.org/assets/images/submissions/a3b3e80c-22f2-4b8f-a3ac-42fe1583e0be.thumb.png"
raylogo = readPNG(getURLContent(rayurl))
#Importing the map
canada = map_data("worldHires", "Canada")
#The Map
ggplot() +
geom_polygon(data = canada,
aes(x=long, y=lat, group=group),
colour="grey50", fill = 'grey55')+
#Coordinates I'm interested in looking at
coord_sf(xlim=c(-64.5,-62.8), ylim=c(42.7,45)) +
geom_point(data = individual_dets,
aes(x = longitude,
y = latitude,
color = as.factor(Zone)),
#fill = as.numeric(Zone)),
size = 5) +
scale_color_manual(values=c("#01579B", "#4FC3F7", "#ffa600", "#ff6361"),
name = "Zone")
Does anyone know how to take this saved silhouette and place it at the same coordinate and as the same color of my points?
Related
I am attempting to map some geom-points/cordinates to a map of the country Sri Lanka. I am able to map the district borders, and the population as expected, but I am having trouble plotting the geom points onto the map.
Install package
devtools::install_github("thiyangt/ceylon")
Load package
library("ceylon")
library(tidyverse)
library(sp)
library(viridis)
data(sf_sl_0)
Mapping only Sri Lanka
ggplot(sf_sl_0) + geom_sf()
Mapping the districts of Sri Lanka + population
ggplot(district) + geom_sf(aes(fill = population), show.legend = TRUE) + scale_fill_viridis()
Mappping specific geom-cordinates onto the map of Sri Lanka districts
These are the cordinates I want to map (yes, they are definitely within SL)
df_cord <- data.frame (lat = c("6.2441521", "6.2234515"),
lon = c("80.0590804", "80.2126109"))
I tried:
ggplot(district) +
geom_sf(df_cord) + scale_fill_viridis() +
geom_point(
data = df_cord,
aes(x = lon, y = lat),
size = 4,
shape = 23,
fill = "darkred"
)
But I get an error: Error in validate_mapping():
! mapping must be created by aes()
It looks like I might need to find the x,y cordinates of every geom point, and then map it with cord_sf? But I am not having an luck figuring out how to do this. I found a cool function called usmap::usmap_transform, which converts US geom points to x,y cordinates... but I can't figure out how to do the same for this map of Sri Lanka.
I am very new to mapping -- could someone please advise? Many thanks! I am open to other approaches/solutions!
One way would be to convert the coordinates to an sf object using st_as_sf and plot them using geom_sf. Don't forget to reproject the data to the same coordinate sistem:
library(ceylon)
library(tidyverse)
library(sp)
library(viridis)
library(sf)
data(district)
df_cord <- data.frame (lat = c(6.2441521, 6.2234515),
lon = c(80.0590804, 80.2126109))
df_cord <- df_cord %>%
st_as_sf(coords = c("lon", "lat"), crs = 4326) %>%
st_transform(crs = st_crs(district)) #reproject coords using the coordinate system of the polygons
#plot
ggplot(district) +
geom_sf(aes(fill = population), show.legend = TRUE) +
geom_sf(data = df_cord ,
size = 4,
shape = 23,
fill = "darkred") +
scale_fill_viridis()
I think you can't assign two data frames in ggplot.
Put the latitude and longitude values inside the geom_point's aes(). Remember that longitude is the x-axis and latitude is the y-axis.
Try this:
ggplot() +
geom_sf(district) +
scale_fill_viridis() +
geom_point(
aes(x = c("80.0590804", "80.2126109"),
y =c("6.2441521", "6.2234515")),
size = 4,
shape = 23,
fill = "darkred"
)
You can add annotations (annotate) which will display your two coordinates. Also, set the right coordinate system like this:
ggplot(district) +
geom_sf(aes(fill = population), show.legend = TRUE) +
annotate("point", x = 80.0590804, y = 6.2441521, colour = "red", size = 2) +
annotate("point", x = 80.2126109, y = 6.2234515, colour = "red", size = 2) +
coord_sf(default_crs = sf::st_crs(4326)) +
scale_fill_viridis()
Output:
I’m currently trying to display my data on a map as points. In fact I got two different data sets of two different studies which I’d like to combine on the map. But my first problem was where to find a map to use for my purpose.
#In the R graphics Cookbook I read about this code to create a map using the ggplot2 package
library(ggplot2)
library(maps)
states_map <- mapd_data(“state”)
ggplot(states_map, aes(x=long, y=lat, group=group)) +
geom_polygon(fill=”white”, colour=”black”) +
#Then I added the data of my two data sets and it worked perfectly fine.
geom_point(data = dat1, aes(x = longitude, y = latitude, group= NA), shape=21, col = "black", fill=”red”, size = dat1$var1) +
geom_point(data = dat2, aes(x = longitude, y = latitude, group= NA), shape=21, col = "black", fill=”blue”, size = dat2$var2)
Now I want to add two legends, one to explain the difference between the point colors and the other to explain the point size. Both data sets can share the same legend for the point size because Var1 and Var2 are on the same scale. But I don’t know how to add custom legends to a ggplot (I even don’t achieve to add any legend to the ggplot). It would be nice to have anything like legend()-function which adds a legend to a normal plot, but I think ggplot wasn’t programmed to solve problems like this on your own. Another approach to solve the problem could be to plot the map without using ggplot.
If you want a legend then you have to map on an aesthetic, i.e. move fill=... and size=... inside aes(). After doing so you could set your desired fill colors via scale_fill_manual:
library(ggplot2)
library(maps)
states_map <- map_data("state")
dat1 <- data.frame(longitude = -110, latitude = 35, var1 = 100)
dat2 <- data.frame(longitude = -90, latitude = 40, var2 = 200)
ggplot(states_map, aes(x=long, y=lat)) +
geom_polygon(aes(group=group), fill="white", colour="black") +
geom_point(data = dat1, aes(x = longitude, y = latitude, fill = "dat1", size = var1), shape=21, col = "black") +
geom_point(data = dat2, aes(x = longitude, y = latitude, fill = "dat2", size = var2), shape=21, col = "black") +
scale_fill_manual(values = c(dat1 = "red", dat2 ="blue"), labels = c(dat1 = "Data 1", dat2 ="Data 2"))
[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()
I am making a map that needs to 2 legends. 1 legend shows the temperature, and another legend shows if points are labelled as zone 1:4. When I try to add the second color scale, for the second legend I get the error
Scale for 'fill' is already present. Adding another scale for
'fill', which will replace the existing scale.
Error: Continuous value supplied to discrete scale
When I don't specify the second color scale I get the map I want however, the points are not the colour I want them to be. I tried using new_scale_color() in the code but that doesn't work either, it's the same error.
Here is some sample data
#Dataframe for Ocean Temperature
mapoc_temp = expand.grid(data.frame(Longitude= seq(-64.5,-62.4,0.1),
Latitude= seq(42.7,44.8,0.1),
year = sample(c(2016,2017,2018), 22, replace = T),
month = sample(month.abb, 22, replace = T)))
mapoc_temp$Ave = runif(nrow(mapoc_temp))
#Dataframe for the points
individual_dets = data.frame(longitude= seq(-64.5,-62.4,0.1),
latitude= seq(42.7,44.8,0.1),
year = sample(c(2016, 2017, 2018), 22, replace = T),
Zone = sample(c(1:4), 22, replace = T),
month = sample(month.abb, 22, replace = T))
This is the code I use to map it, you will need this entire code to see my error.
library(mapdata)
#Import Canada map
canada = map_data("worldHires", "Canada")
## Map of temperature across Scotian Shelf
ggplot(mapoc_temp, aes(x=Longitude, y=Latitude)) +
#plotting the temperature as color
geom_raster(aes(fill = Ave,
x = Longitude), interpolate = TRUE) +
#getting the map of Scotian shelf
geom_polygon(data = canada,
aes(x=long, y=lat, group=group),
colour="grey50", fill = 'grey55')+
#Coordinates I'm interested in looking at
coord_sf(xlim=c(-64.5,-62.8), ylim=c(42.7,45)) +
scale_fill_viridis_c(name = "Temp.\n(°C)", option = "C") +
#Use this to get second legend?
new_scale_color() +
#to try and get zones overtop
geom_point(data = individual_dets,
aes(x = longitude,
y = latitude,
color = as.numeric(Zone),
fill = as.numeric(Zone)),
pch = 21, size = 2) +
#fill the zones with second legend.... Does not work
scale_fill_manual(values=c("#01579B", "#4FC3F7", "#ffa600", "#ff6361")) +
scale_color_manual(values=c("#01579B", "#4FC3F7", "#ffa600", "#ff6361"))
If I don't use the last chunk of code
#fill the zones with second legend.... Does not work
scale_fill_manual(values=c("#01579B", "#4FC3F7", "#ffa600", "#ff6361")) +
scale_color_manual(values=c("#01579B", "#4FC3F7", "#ffa600", "#ff6361"))
I get this picture
But I need the points to be those exact colors I have in the chunk of code. Does anyone know how to add the second legend scale to the ggplot map?
If you don't use a pch = 21, ggplot will use a point with color being the same fill (I guess it is pch = 16 by default), so, you don't need twice scale_fill but instead can manipulate points using scale_color_manual.
Also, you are converting Zone in a numeric format so ggplot2 is plotting it as a continuous scale. So, you can't pass only 4 color values on it. Either, you have to plot Zone as a factor and use scale_color_manual to set the color for each zone (which makes sense) or you can plot Zone as a gradient as you are doing but you need to use scale_color_gradient then to set the color scheme.
library(mapdata)
library(ggplot2)
ggplot(mapoc_temp, aes(x=Longitude, y=Latitude)) +
geom_raster(aes(fill = Ave,
x = Longitude), interpolate = TRUE) +
geom_polygon(data = canada,
aes(x=long, y=lat, group=group),
colour="grey50", fill = 'grey55')+
coord_sf(xlim=c(-64.5,-62.8), ylim=c(42.7,45)) +
scale_fill_viridis_c(name = "Temp.\n(°C)", option = "C") +
geom_point(data = individual_dets,
aes(x = longitude,
y = latitude,
color = as.factor(Zone)),
#fill = as.numeric(Zone)),
size = 2) +
scale_color_manual(values=c("#01579B", "#4FC3F7", "#ffa600", "#ff6361"), name = "Zone")
Does it look what you are trying to achieve ?
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)