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.
Related
[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 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
In my previous question, I presented that I have a table of "posts" with IPs, and that I wanted to geolocate them.
Geolocating a large number of posts based on IP Addresses. (880,000 rows)
The answer demonstrated how to use rgeolocate to achieve this, and after some effort in learning R I have managed to accomplish the same result:
library(iptools)
library(rgeolocate)
library(tidyverse)
library(readxl)
library(rworldmap)
library(ggmap)
library(rworldxtra)
post <- read_excel("filepath/post.xlsx")
view(post)
## grab my ips and, format them
ips <- unlist(post[,3], use.names=FALSE)
#geolocte them
system.time(
rgeolocate::maxmind(
ips, "~/R/GeoLite2-City.mmdb", c("longitude", "latitude")
) -> xdf
)
#user system elapsed
#6.04 0.02 6.05
xdf %>%
count(longitude, latitude) -> pts
#And, plot them:
ggplot(pts) +
geom_point(
aes(longitude, latitude, size = n),
shape=21, fill = "steelblue", color = "white", stroke=0.25
) +
ggalt::coord_proj("+proj=wintri") +
ggthemes::theme_map() +
theme(legend.justification = "center") +
theme(legend.position = "bottom")
The result is shown here:
This plot shows exactly the sort of grouping that I would expect, based on the data. So one step of success!
Of course, the next logical step is to increase the resolution and add an overlay of a world map. I have been unable to achieve either of these goals.
Using this code, I can make a high resolution world map:
newmap <- getMap(resolution = "high")
plot(newmap)
And the result is shown here:
Somehow I just can't achieve a combination of the map AND the data being plotted. It seems like any attempt to create the map needs me to plot the map itself, and any attempt to add points to that fail. For example:
newmap <- getMap(resolution = "high")
plot(newmap)
ggmap(newmap) +
geom_point(data = pts, aes(x = longitude, y = latitude, size=n),
shape=21, fill = "steelblue", color = "white", stroke=0.25)
Error: ggmap plots objects of class ggmap, see ?get_map
I have been trying to work based on the advice of http://www.milanor.net/blog/maps-in-r-plotting-data-points-on-a-map/ but this website focuses on a map of Europe, and I want to show my data on a map of the world.
Thank you for your help.
library(iptools)
library(rgeolocate)
library(tidyverse)
ips <- ip_random(1000000)
rgeolocate::maxmind(
ips, "~/Data/GeoLite2-City.mmdb", c("longitude", "latitude")
) -> xdf
xdf %>%
mutate(
longitude = (longitude %/% 5) * 5,
latitude = (latitude %/% 5) * 5
) %>%
count(longitude, latitude) -> pts
wrld <- tbl_df(map_data("world"))
wrld <- filter(wrld, region != "Antarctica")
ggplot() +
geom_map(
map = wrld, data = wrld, aes(long, lat, map_id=region),
color = "black", fill ="white", size=0.125
) +
geom_point(
data = pts, aes(longitude, latitude, size = n),
shape=21, fill = "steelblue", color = "white", stroke=0.25
) +
scale_size(name = "# IPs", label=scales::comma) +
ggalt::coord_proj("+proj=wintri") +
ggthemes::theme_map() +
theme(legend.justification = "center") +
theme(legend.position = "bottom")
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().
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")