how to use a picture as coordinate system? - r

I have a question plotting with R: I have x-y-coordinates that are based on pixels (a 658px x 402px jpg picture). I want to plot the x-y-Coordinates WITH the picture (a map) as a background.
I tried this, but as it turns out there is something wrong; the points should be in the north sea (all of them)
d <- read.csv("~/Dropbox/IMITATION3/d.csv", sep=";")
library(ggplot2)
library(jpeg)
library(grid)
ima <- readJPEG("~/Dropbox/IMITATION3/image.jpg")
ggplot(d, aes(IM02_cx, IM02_cy)) +
annotation_custom(rasterGrob(ima, width=unit(1,"npc"), height=unit(1,"npc")),
-Inf, Inf, -Inf, Inf) +
stat_bin2d(bins = 55) +
scale_x_continuous(expand=c(0,0)) +
scale_y_reverse(expand=c(0,0))
Here is the image:
CSV:
CASE;IM02_cx;IM02_cy
412;191;75
127;222;74
459;220;73
80;138;72
86;225;72
458;156;71
71;86;69
289;219;69
291;219;68
77;221;68
338;199;67
495;200;67
371;138;66
197;227;66
64;134;65
105;170;65
124;196;65
237;171;64
350;213;64
63;92;63
305;106;63
286;139;63
99;199;63
353;201;63
362;198;62
452;168;60
479;204;60
65;209;60
330;214;60
132;101;59
162;184;59
93;182;58
249;209;58
49;117;57
106;172;57
83;150;56
282;168;56
234;190;56
492;165;55
40;181;55
448;195;55
262;184;54
199;165;53
47;92;52
109;143;52
107;147;52
97;208;51
467;145;50
98;169;50
451;169;49
480;117;48
414;96;47
424;122;47
466;143;47
514;170;47
465;133;45
176;172;45
69;183;45
417;109;44
220;140;44
160;96;43
172;128;43
48;132;43
344;156;43
490;163;43
396;182;43
374;163;41
327;172;41
128;173;41
408;82;40
53;147;40
409;158;40
225;71;38
402;70;37
469;149;34
284;99;32
455;163;32
149;174;21
PS: I don't know why but I had to reverse my y-scale to get the points (basiclly) at the right angle...–

You are making the coordinate reference system your image, so you have to deal with the "projection" manually. You can also use ggimage from the ggmap package. The following assumes your data is in dat:
library(ggplot2)
library(ggmap)
library(jpeg)
library(grid)
ima <- readJPEG("image.jpg")
gg <- ggimage(ima)
gg <- gg + geom_point(data=dat, aes(x=IM02_cx, y=nrow(ima)-IM02_cy))
gg

As an alternative, you could also add + xlim(c(0, ncol(ima))) and + ylim(nrow(ima), 0) to your existing plot.

Related

Overlay bathymetric data onto OSM multipolygons

I want to draw the map of a lake with the bathymetries I have taken with the sonar. I have a .sl2 file (Lowrance sonar) that I have converted to .csv (Namely, Sonar_13_07_1.csv). Finally I get 3 columns with 30665 rows, here is an example of the first rows:
latitude,longitude,waterDepthM
39.8197123940846,-3.11133523036904,0
39.8197193169248,-3.11133523036904,0
39.8197193169248,-3.11134424374202,0
39.8197262397644,-3.11134424374202,0
39.8197331626032,-3.11135325711499,0
39.8197400854413,-3.11135325711499,0
39.8197470082787,-3.11135325711499,0
39.8197539311154,-3.11135325711499,0
39.8197608539514,-3.11135325711499,0
39.8197608539514,-3.11134424374202,0
39.8197677767867,-3.11134424374202,0
39.8197677767867,-3.11135325711499,0
39.8197746996213,-3.11135325711499,0
39.8197746996213,-3.11134424374202,0
39.8197816224553,-3.11134424374202,0
39.8197885452885,-3.11134424374202,0
39.8197885452885,-3.11133523036904,0
39.819795468121,-3.11133523036904,0
39.8198023909528,-3.11132621699607,0
39.8198023909528,-3.11133523036904,0
39.819809313784,-3.11132621699607,0
39.8198162366144,-3.11132621699607,0
39.8198231594442,-3.11132621699607,0
39.8198370051015,-3.11132621699607,0
39.8198300822732,-3.11132621699607,0
39.8198439279292,-3.11132621699607,0
39.8198508507561,-3.11133523036904,0
39.8198508507561,-3.11132621699607,0
39.8198577735824,-3.11133523036904,0
39.8198646964079,-3.11133523036904,0
39.8198646964079,-3.11134424374202,0
39.8198716192328,-3.11135325711499,0
39.8198716192328,-3.11134424374202,0
39.8198716192328,-3.11136227048797,0
39.8198785420569,-3.11135325711499,0
39.8198716192328,-3.11136227048797,-0.691144658182553
39.8198785420569,-3.11135325711499,-0.691144658182553
39.8198716192328,-3.11136227048797,-0.72783260768886
39.8198785420569,-3.11135325711499,-0.72783260768886
39.8198716192328,-3.11136227048797,-0.735494858005278
39.8198785420569,-3.11135325711499,-0.735494858005278
39.8198716192328,-3.11136227048797,-0.754367615888273
39.8198785420569,-3.11135325711499,-0.754367615888273
39.8198716192328,-3.11136227048797,-0.762954301055886
39.8198785420569,-3.11135325711499,-0.762954301055886
39.8198785420569,-3.11136227048797,-0.762954301055886
I manage to plot it like this:
library(ggplot2)
ggplot(Sonar_13_07_1, aes(longitude, latitude, colour = waterDepthM)) + geom_point() + coord_equal() + xlim(x_coords) + ylim(y_coords)
On the other hand, I plotted the base map of the lake:
library(osmdata)
library(sf)
> x_coords <- c(-3.109, -3.117)
> y_coords <- c(39.817, 39.832)
> bounding_box <- matrix(nrow = 2, ncol=2, byrow = T,
+ data = c(x_coords, y_coords),
+ dimnames = list(c("x", "y"),
+ c("min", "max")))
> osm_water_sf <- osmdata::opq(bbox = bounding_box) %>% # Limit query to bounding_box
+ osmdata::add_osm_feature(key = 'natural', value = 'water') %>% # Limit query to waterbodies
+ osmdata::osmdata_sf() # Convert to simple features
ggplot(data=osm_water_sf$osm_polygons) +
geom_sf(color="blue", fill="lightblue") +
xlim(x_coords) + ylim(y_coords)
But finally I don't manage to merge the two plots into one, superimposing the bathymetric data on the base map. Also, my intention would be to obtain contours from the bathymetric data of the lake, but of course, I'm already stuck with the merging of both plots.
Thanks for the suggestion, I have managed to have a spatial data frame like this:
"","waterDepthM","geometry"
"1",0,c(-3.11133523036904, 39.8197123940846)
"2",0,c(-3.11133523036904, 39.8197193169248)
"3",0,c(-3.11134424374202, 39.8197193169248)
"4",0,c(-3.11134424374202, 39.8197262397644)
"5",0,c(-3.11135325711499, 39.8197331626032)
"6",0,c(-3.11135325711499, 39.8197400854413)
"7",0,c(-3.11135325711499, 39.8197470082787)
"8",0,c(-3.11135325711499, 39.8197539311154)
"9",0,c(-3.11135325711499, 39.8197608539514)
"10",0,c(-3.11134424374202, 39.8197608539514)
but when I try to plot both data frames together, I only get a base map of the lake with the depth legend, but no depth values appear.
ggplot() +
+ geom_sf(data=osm_water_sf$osm_polygons, color="blue", fill="NA") +
+ geom_sf(data=Sonar_13_07_1, aes(col=waterDepthM)) +
+ xlim(x_coords) + ylim(y_coords)
plot output
Use the sf package to convert your sonar data frame to a spatial data frame. Something like:
library(sf)
Sonar_13_07_1 = st_as_sf(Sonar_13_07_1, coords=c("longitude","latitude"), crs=4326)
then you have an object you can put in a ggplot construction via an sf geom alongside your OSM vector data. Something like:
ggplot(data=osm_water_sf$osm_polygons) +
geom_sf(color="blue", fill="lightblue") +
geom_sf(data=Sonar_13_07_1, aes(col=waterDepthM)) +
xlim(x_coords) + ylim(y_coords)

Getting "missing aesthetics error" while using ggplot2's geom_errorbar

my code looks like this
Q <- c(1.624e-05, 1.583e-05, 1.540e-05, 1.512e-05, 1.487e-05, 1.420e-05, 1.334e-05, 1.270e-05, 1.239e-05, 1.180e-05, 1.081e-05, 9.720e-06, 8.880e-06, 7.770e-06, 6.740e-06, 5.790e-06, 4.430e-06, 3.410e-06)
diP <- c(4443.93, 4022.10, 3698.37, 3423.69, 3237.30, 2943.00, 2668.32, 2501.55, 2383.83, 2148.39, 1952.19, 1618.65, 1422.45, 1177.20, 1010.43, 814.23, 559.17, 343.35)
eQ <- c(1.6e-06, 1.6e-06, 1.6e-06, 1.5e-06, 1.5e-06, 1.4e-06, 1.3e-06, 1.3e-06, 1.2e-06, 1.2e-06, 1.1e-06, 1.0e-06, 9.0e-07, 8.0e-07, 7.0e-07, 6.0e-07, 5.0e-07, 4.0e-07)
ediP <- seq(10,10,length=18)
ggplot() + stat_smooth(aes(diP[10:18],Q[10:18]),method = "lm",col="red",se=F) + geom_point(aes(diP,Q)) +
geom_errorbar(aes(ymin=Q-eQ, ymax=Q+eQ), width=.1) +
xlab(expression(paste(Delta,"p (Pa)"))) + ylab(expression(paste("Q (",m^3,"/s)")))
When I run all, I get the following error:
Error: geom_errorbar requires the following missing aesthetics: x or
y, xmin and xmax
Ty in advance!
You could provide x=diP as the x variable, but I'm going to recommend two best practices for working with ggplot: (1) use the data argument explicitly (don't grab variables from the global workspace) (2) allow aesthetics to be inherited whenever it makes sense. This gets me to:
dd <- data.frame(Q, diP, eQ, ediP)
ggplot(dd, aes(x=diP, y=Q)) +
stat_smooth(data=dd[10:18,],
method = "lm",col="red",se=FALSE) +
geom_point() +
geom_errorbar(aes(ymin=Q-eQ, ymax=Q+eQ), width=.1) +
xlab(expression(paste(Delta,"p (Pa)"))) +
ylab(expression(paste("Q (",m^3,"/s)")))
by specifying data=dd and the mapping in the initial ggplot(), you are allowing these mappings to be inherited by subsequent geoms. I overrode the data argument in the stat_smooth to make sure only the appropriate subset of the data got used.

geographical/geospatial map with maps() - R

I have been through a lot of questions and documentation, and since you need to bill to use ggmaps() (because of google cloud services) I started looking for an alternative. I found maps(), and I'm trying to adapt this solution:
data %>%
rename(x = longitud, y = latitud) %>%
ggplot() +
geom_polygon(aes(x = long, y = lat), data = map_data("world")) +
geom_point(aes(x = x, y = y))
However, I'm getting into a few problems:
If you plot the code above, you will get the right points for the plot (Chile), but the world map is wrongly printed (see the picture above).
I don't need a grey either a colorful map. I just need to plot the country Chile with kind-of-normal formatting (for example, google maps satellite). The coordinates are flows of lakes/mountains and I want to see if I can cluster them by some-visual sector.
I only need a map from Chile, but as I didn't find one I'm using this world map. Is there a way to cut it without losing the connections with the map coordinates?
This is the data:
data <- structure(list(latitud = c(-30.6833000183105, -41.4000015258789,
-43.8189010620117, -34.2731018066406, -47.0666999816895, -40.3166999816895,
-43.4491996765137, -35.7543983459473, -47.1413993835449, -36.6260986328125,
-54.0410995483398, -37.2118988037109, -33.3086013793945, -37.2792015075684,
-35.4524993896484, -36.5856018066406, -18.5832996368408, -18.2325000762939,
-36.4668998718262, -44.75, -44.6591987609863, -44.5936012268066,
-28.4647006988525, -28.6996994018555, -28.5118999481201, -28.6718997955322,
-28.7306003570557, -30.5902996063232, -30.6667003631592, -35.1730995178223,
-48.1591987609863, -48.377498626709, -45.4000015258789, -45.7832984924316,
-29.94580078125, -38.8652992248535, -30.4386005401611, -31.6646995544434,
-51.2000007629395, -51.3328018188477, -51.25, -45.5666999816895,
-45.551700592041, -45.8372001647949, -39.0144004821777, -28.9414005279541,
-28.7502994537354, -38.6081008911133, -34.9844017028809, -32.8403015136719,
-29.9953002929688, -18.3999996185303, -35.9000015258789, -35.6169013977051,
-35.9085998535156, -35.8166999816895, -33.7346992492676, -45.38330078125,
-35.4068984985352, -32.7571983337402, -32.8502998352051, -33.5938987731934,
-36.8386001586914, -33.4961013793945, -20.1119003295898, -27.8043994903564,
-37.7332992553711, -30.9986000061035, -30.8006000518799, -21.9368991851807,
-22.3652992248535, -22.273099899292, -22.0277996063232, -21.9755992889404,
-22.289400100708, -22.2791996002197, -38.4303016662598, -38.6866989135742,
-45.4057998657227, -38.7799987792969, -37.5503005981445, -37.6018981933594,
-37.8997001647949, -38.0368995666504, -37.9897003173828, -37.7047004699707,
-37.7963981628418, -37.7092018127441, -31.5835990905762, -27.3635997772217,
-27.3194007873535, -29.8931007385254, -30.9242000579834, -21.4246997833252,
-36.5703010559082, -38.2008018493652, -38.0661010742188, -38.4333000183105,
-31.7422008514404, -31.6881008148193, -31.8117008209229, -31.7714004516602,
-27.86669921875, -27.5160999298096, -27.9747009277344, -30.7047004699707,
-36.8499984741211, -36.6500015258789, -36.86669921875, -35.3736000061035,
-40.5167007446289, -33.4782981872559, -33.198299407959, -36.0499992370605,
-35.9667015075684, -36.2332992553711, -34.4921989440918, -34.6581001281738,
-32.8166999816895, -47.3499984741211, -47.5, -29.9811000823975,
-32.4413986206055, -22.3922004699707, -22.3430995941162, -21.7124996185303,
-22.4582996368408, -22.4419002532959, -22.4468994140625, -22.5060997009277,
-33.7219009399414, -33.6613998413086, -35.5574989318848), longitud = c(-71.0500030517578,
-73.2166976928711, -72.38330078125, -71.371696472168, -72.8000030517578,
-72.9666976928711, -72.1074981689453, -71.0864028930664, -72.7257995605469,
-72.4891967773438, -68.7975006103516, -72.3242034912109, -70.3572006225586,
-71.9847030639648, -71.7332992553711, -71.5255966186523, -69.0466995239258,
-69.331901550293, -72.6911010742188, -72.7166976928711, -71.8082962036133,
-71.5477981567383, -71.1782989501953, -70.5500030517578, -71.0064010620117,
-70.6464004516602, -70.5066986083984, -71.1714019775391, -71.5333023071289,
-71.0911026000977, -73.0888977050781, -72.9589004516602, -72.5999984741211,
-72.61669921875, -70.5327987670898, -71.7335968017578, -71.002197265625,
-71.2546997070312, -72.9332962036133, -73.1091995239258, -72.5167007446289,
-72.0832977294922, -72.0680999755859, -71.7769012451172, -73.0828018188477,
-70.2481002807617, -70.4828033447266, -72.8478012084961, -72.0100021362305,
-71.0255966186523, -70.5867004394531, -70.3000030517578, -71.5167007446289,
-71.7677993774414, -71.2981033325195, -71.8332977294922, -70.3007965087891,
-72.4666976928711, -72.2082977294922, -70.736701965332, -70.5093994140625,
-70.3792037963867, -73.061897277832, -70.8167037963867, -68.8407974243164,
-70.1268997192383, -72.61669921875, -71.0899963378906, -70.9697036743164,
-68.5330963134766, -68.6418991088867, -68.1438980102539, -68.6207962036133,
-68.6074981689453, -68.3447036743164, -68.2427978515625, -72.0105972290039,
-72.502799987793, -72.6231002807617, -72.9468994140625, -72.5903015136719,
-72.2782974243164, -71.6239013671875, -71.4781036376953, -71.5199966430664,
-71.7683029174805, -71.6988983154297, -71.823600769043, -71.4606018066406,
-70.3392028808594, -70.8380966186523, -71.2514038085938, -70.7731018066406,
-70.053596496582, -71.5547027587891, -71.2988967895508, -71.3497009277344,
-71.2332992553711, -71.1492004394531, -71.2658004760742, -70.9302978515625,
-71.0639038085938, -70.0667037963867, -70.2647018432617, -69.997802734375,
-70.9244003295898, -72.38330078125, -72.4499969482422, -72.3332977294922,
-71.8292007446289, -73.2833023071289, -70.7172012329102, -70.8955993652344,
-72.0832977294922, -72.0167007446289, -72, -71.3731002807617,
-71.3019027709961, -71, -72.8499984741211, -72.9749984741211,
-70.8981018066406, -71.3139038085938, -69.5299987792969, -69.5650024414062,
-69.5167007446289, -68.7363967895508, -68.8886032104492, -68.8775024414062,
-68.988899230957, -71.5550003051758, -71.3371963500977, -71.7067031860352
)), row.names = c(1L, 136L, 262L, 395L, 507L, 605L, 701L, 789L,
868L, 996L, 1094L, 1124L, 1172L, 1218L, 61387L, 61546L, 75009L,
87052L, 99246L, 110237L, 115091L, 125346L, 135758L, 135819L,
144524L, 154009L, 172251L, 185024L, 192338L, 210797L, 228781L,
228893L, 238299L, 244626L, 253673L, 274263L, 285367L, 304757L,
316768L, 328069L, 336044L, 346167L, 351691L, 363302L, 375494L,
385229L, 402720L, 422016L, 440373L, 451547L, 462674L, 483188L,
491968L, 496483L, 511332L, 530494L, 546443L, 564800L, 575215L,
586462L, 602135L, 622841L, 642834L, 657640L, 677273L, 688216L,
706550L, 724524L, 731829L, 748442L, 748489L, 754030L, 763570L,
776729L, 785860L, 799355L, 812606L, 832675L, 853030L, 860670L,
878448L, 889066L, 889167L, 889273L, 889372L, 889466L, 889499L,
889524L, 913996L, 929594L, 935459L, 953842L, 963352L, 983829L,
991810L, 1005230L, 1005341L, 1011503L, 1022492L, 1029507L, 1047978L,
1063655L, 1073799L, 1073936L, 1086040L, 1106251L, 1126146L, 1134776L,
1154269L, 1170495L, 1181431L, 1192018L, 1197439L, 1212431L, 1231028L,
1247598L, 1264197L, 1264302L, 1271900L, 1279499L, 1279618L, 1290282L,
1309415L, 1320521L, 1320606L, 1320753L, 1320827L, 1337638L, 1344817L,
1355030L, 1368899L, 1381979L, 1393175L), class = "data.frame")
The following code uses the simple features (sf) library to show a map of Chile overlaid with the provided datapoints. The bounding box is set in the parameters to st_crop and can be adjusted as needed without distorting the map. The code uses the Admin 0 - Countries shape file, which is in the public domain and free to use.
library(sf)
library(ggplot2)
library(dplyr);
library(magrittr);
# download world shapefile from
# https://www.naturalearthdata.com/downloads/
# 50m-cultural-vectors/50m-admin-0-countries-2/
# and extract zip file
world <- st_read(
# change below line to path of extracted shape file
'c:/path/to/ne_50m_admin_0_countries.shp'
);
world %<>% mutate(active = NAME_EN == 'Chile'); # used to highlight Chile
# convert the dataframe to a sf geometry object
dsf <- data %>%
rowwise %>%
mutate(geometry = list(st_point(c(longitud, latitud)))) %>%
st_as_sf(crs=st_crs(world));
# plot the map
world %>% st_crop(xmin=-90, xmax=-30, ymin=-60, ymax=-10) %>%
ggplot() +
geom_sf(aes(fill=active), show.legend=F) + # world map with Chile highlighted
geom_sf(data=dsf, color='#000000') + # point overlay
scale_fill_manual(values=c('#aaaa66', '#ffffcc')) + # country colors
scale_x_continuous(expand=c(0,0)) +
scale_y_continuous(expand=c(0,0)) +
theme_void() + # remove axis labels and gridlines
theme(panel.background=element_rect(fill='lightblue'))
The output is shown below. Note that the map does not distort regions that are cropped.
Additional explanation
The sf package provides support for simple feature (sf) geometries. Simple features provide tools for working with geometries such as polygons and points. There is a cheat sheet here that provides a good overview.
Plotting the base map
As of release 3.0, ggplot2 provides native support for visualizing simple feature geometries. This allows for us to write:
world <- st_read(
# change below line to path of extracted shape file
'c:/path/to/ne_50m_admin_0_countries.shp'
);
ggplot(world) + geom_sf()
Simple feature objects are generally stored in data frames that include a column describing the geometry. This allows us to show a map of Chile like so:
ggplot(world %>% filter(NAME_EN == 'Chile')) + geom_sf()
Or a map with Chile highlighted:
# create new geometry of world map
# cropped to (10°S, 60°S) and (90°W, 30°W)
chileregion <- world %>% st_crop(
xmin=-90,
xmax=-30,
ymin=-60,
ymax=-10)
# show region with Chile highlighted
ggplot(chileregion %>%
mutate(is.chile = factor(NAME_EN == 'Chile'))) +
geom_sf(aes(fill=is.chile), show.legend = F) +
scale_fill_manual(values=c('gray', 'red'))
Plotting the points
We are given a data frame with two columns, latitude and longitude.
To convert to a simple feature, we first use st_point to create a new point with the given coordinate values:
dsf <- data %>% #begin with data
rowwise %>% # dplyr::rowwise applies mutation to each row individually
# create a geometry column that provides the point as a geometry
mutate(geometry = list(st_point(c(longitud, latitud))))
At this point, dsf is simply a data frame with a geometry column; it is not yet a simple feature object. We can use the function st_as_sf to create a sf object from the data frame. In doing so, we will also need to provide a coordinate reference system (CRS) to allow ggplot to project the coordinates provided onto the map rendering. Here we can provide ESPG 4326 as the CRS, which maps the x and y coordinates directly to lat/long:
# call st_as_sf to convert data frame to a simple geometry object.
dsf <- st_as_sf(crs=4326);
Since dsf is now a simple geometry, you can plot as such:
> ggplot(dsf) + geom_sf()
(Note that you could also simply overlay the points on the base map with geom_point(data=data, aes(x=longitud, y=latitud)) without first converting to an sf object. This will work here because the CRS for the base map is also ESPG 4326, which maps x and y directly to longitude and latitude, respectively. Using geom_point, however, will not work in the general case when a coordinate transformation is applied to the geometry.)
Overlaying
With both points now defined as geometries, you can simply overlay:
ggplot() +
geom_sf(data=chileregion) +
geom_sf(data=dsf)
The final plot in the original answer adds some additional visual aesthetics (e.g., blue background) to produce the final map output.
This might help and you can play around with it yourself:
world_map <- map_data("world")
Wmap <- data %>%
rename(x =longitud , y = latitud) %>%
ggplot() +
geom_polygon(aes(x = long, y = lat, group = group), data = world_map, fill = "grey21", color = "grey21") +
geom_point(aes(x = x, y = y, color = 'red')) +
scale_color_identity() +
coord_fixed() +
xlab("") +
ylab("")
Wmap
Chile_map <- map_data("world", region="Chile")
Cmap <- data %>%
rename(x =longitud , y = latitud) %>%
ggplot() +
geom_polygon(aes(x = long, y = lat, group = group), data = Chile_map, fill = "grey21", color = "grey21") +
geom_point(aes(x = x, y = y, color = 'red')) +
scale_color_identity() +
coord_fixed() +
xlab("") +
ylab("")
Cmap
dev.new()
windows.options(width=10, height=6)
vp_inset <- grid::viewport(width = 0.55, height = 0.45, x = -0.1, y = 0.60, just = c("left", "top"))
print(Wmap)
print(Cmap, vp = vp_inset)
NOTE: The group aesthetic determines which cases are connected together into a polygon.

plotly not getting geom_text in R / ggplot

I have a ggplot that works fine by its own. But when I try to import it in to the plotly api system, the geom_text seems to not work - everything else works. Can anyone help me?
Here's my R version - R version 3.1.2 (2014-10-31)
and plotly version - 0.5.23
The data that I am using is in file.csv and looks like:
Province,Community,General Shelters,General Beds,Mens Shelters,Mens Beds,Womens Shelters,Womens Beds,Youth Shelters,Youth Beds,Family Shelters,Family Beds,Total Shelters,Total Beds
New Brunswick,Saint John,0,0,1,35,1,10,0,0,0,0,2,45
Quebec,Montréal,7,114,9,916,12,259,17,197,1,7,45,"1,493"
Quebec,Québec City,3,49,2,102,1,12,2,15,0,0,8,178
Ontario,Toronto,4,250,13,"1,483",10,572,10,416,4,496,41,"3,217"
British Columbia,Vancouver,13,545,7,291,9,238,7,90,2,30,38,"1,194"
British Columbia,Victoria,1,84,1,21,1,25,1,10,1,5,5,145
And here's my full code:
library(ggplot2)
library(zoo)
library(DAAG)
library(mapdata) #for canada map from worldhires database
library(ggmap)
library("plotly") # for plotly
homeless <- function()
{
allcit <- NULL
#read csv
allcittmp <- read.csv("file.csv", sep=",", header=TRUE, colClasses="character")
#cast data to proper format from character for both data frames
allcittmp[,1] <- as.character(allcittmp[,1])
allcittmp[,2] <- as.character(allcittmp[,2])
allcittmp[,13] <- as.integer(allcittmp[,13])
allcittmp[,14] <- as.integer(gsub(",","",allcittmp[,14]))
#get only relevant columns to a new data frame
allcit <- allcittmp[,c(1,2,13,14)]
#delete temp data frames for hygiene
allcittmp <- NULL
#give better colnames
colnames(allcit) <- c("prov","community","totshelters","totbeds")
#concatenate col2,1 to get city, province
allcit$hcity <- paste(allcit$community,allcit$prov, sep=", ")
#clean up NA's
allcit <- na.omit(allcit)
plmap <- mapcit3(allcit$hcity, allcit$totshelters, allcit$community)
#the following two lines commented out makes plotly graph
#everything is fine except that the city names don't show up
#py <- plotly()
#py$ggplotly(plmap)
}
mapcit3 <- function(citiesM, indM, cityname)
{
#concatenate Canada to city names, to be safe and not pick up similar US cities:
citiesM <- paste(citiesM,", Canada", sep="")
freqM <- data.frame(citiesM, indM, cityname) #make dataframe
lonlat <- geocode(citiesM) #courtesy of google, logitude, lattitude (gives two var's lon, lat among others)
citiesC <- cbind(freqM,lonlat) #make new df with long/lat
mappts2 <- ggplot(citiesC, aes(lon, lat)) +
borders(regions="canada", name="borders") +
coord_equal() +
geom_point(aes(text=cityname, size=indM), colour="red", alpha=1/2, name="cities", label=citiesC$cityname) +
geom_text(size=2, aes(label=cityname),hjust=0, vjust=0)
return(mappts2)
}
Attached as map1_without_plotly.png is the version without plotly:
And the map with plotly that appears on the plotly site as an API: (yes, the plotly version has more cities, but that is because I stripped down the csv file for stack overflow, so it is easily reproducible)
But basically the plotly version is missing the geom_text (city names) that are in the non-plotly version.
Okay, I spotted several shortcomings in the ggplotly conversion. For now, I can suggest the following workaround:
mappts2 <- ggplot(citiesC, aes(x=lon, y=lat)) +
geom_text(size=10, aes(label=cityname), hjust=0, vjust=0) +
borders(regions="canada", name="borders") +
coord_equal() +
geom_point(aes(text=cityname, size=indM), colour="red", alpha=0.5,
name="cities", label=citiesC$cityname)
# Take a look
mappts2
# Yes, text is too big in ggplot2
first_version <- py$ggplotly(mappts2, kwargs=list(filename="map_text",
fileopt="overwrite"))
# Has the labels, misses the markers
my_account <- "marianne2" # Replace with yours
account_url <- paste0("https://plot.ly/~", my_account, "/")
plot_number <- as.integer(gsub(account_url, "", first_version$response$url))
text_marker <- py$get_figure(my_account, plot_number)
text_marker$data[[1]]$mode
# Says "text"
text_marker$data[[1]]$mode <- "text+markers"
final_version <- py$plotly(text_marker$data,
kwargs=list(layout=text_marker$layout,
fileopt="overwrite",
filename="text_markers_mode"))
# Visit final_version$url
Size conversion is not perfect, hence my replacement of size=2 with size=10.
Unfortunately arguments hjust and vjust are not supported (ignored here).
When geom_text and geom_point are used on the same data, ggplotly should set mode="text+markers", which is not currently the case in the R "plotly" package (version 0.5.25).
read.csv() has defaults header=TRUE, sep="," so you don't need to specify these.
If you have run allcittmp <- read.csv("file.csv", colClasses="character") you don't need to do the
for (i in c(1, 2)) {
allcittmp[, i] <- as.character(allcittmp[, i])
}
because that's precisely what colClasses="character" takes care of.
I'm not too fond of the mapcit3() function, which seems to be doing some processing and then some plotting(?!).

ggplot2 and maps: geom_point and annotation_raster position mismatch

Good day everyone,
Using the code below I can successfully retrieve a raster from Google using ggmap, plot an annotation_raster using ggplot2, and plot site localities as red dots on top of the raster layer. On the plot the positions don't quite match (they should follow the coastline). I know my sites' positions are correct because they plot where they should be when I upload the data onto Google Earth as a KML file.
Suggestions will be appreciated.
This code will run as is... Note that you need a development version of ggplot2, which is available on github. To install:
# install.packages("devtools")
library(devtools)
install_github("ggplot2")
and for the code:
library(ggplot2)
library(ggmap)
library(grDevices)
theme_set(theme_bw())
# Some coordinates of points to plot:
siteLat = c(-22.94414, -22.67119, -29.25241, -30.31181, -32.80670, -33.01054, -32.75833, - 33.36068, -31.81708, -32.09185, -32.31667, -34.13667, -34.05016, -33.91847, -34.13525, -34.12811, -34.10399, -34.16342, -34.41459, -34.58786, -34.83353, -34.37150, -34.40278, -34.17091, -34.08565, -34.04896, -33.98066, -34.02448, -34.20667, -34.05889, -33.97362, -33.99125, -33.28611, -33.02407, -33.01798, -32.99316, -31.09704, -31.05000, -30.91622, -30.70735, -30.28722, -30.27389, -29.86476, -29.54501, -29.49660, -29.28056, -28.80467, -27.42472)
siteLon = c(14.50175, 14.52134, 16.86710, 17.26951, 17.88522, 17.95063, 18.02778, 18.15731, 18.23065, 18.30262, 18.32222, 18.32674, 18.34971, 18.38217, 18.43592, 18.45077, 18.48364, 18.85908, 19.25493, 19.33971, 20.00439, 21.43518, 21.73972, 22.12749, 23.05532, 23.37925, 23.64567, 23.89933, 24.77944, 25.58889, 25.64724, 25.67788, 27.48889, 27.91626, 27.92182, 27.95036, 30.18395, 30.21666, 30.32982, 30.48474, 30.76026, 30.83556, 31.04479, 31.21662, 31.24665, 31.44403, 32.07567, 32.73333)
siteName = c(seq(1:length(siteLon)))
sites <- as.data.frame(cbind(siteLat, siteLon, siteName))
# specify raster's approximate coordinates:
lats = c(-35, -20)
lons = c(10, 35)
SAMap <- GetMap.bbox(lons, lats, maptype = "satellite")
# extract "real" coords of raster:
lonr <- c(SAMap$BBOX$ll[2], SAMap$BBOX$ur[2])
latr <- c(SAMap$BBOX$ll[1], SAMap$BBOX$ur[1])
# extract raster fill data:
h_raster <- as.raster(SAMap$myTile)
# plot using annotation_raster:
g <- ggplot(sites, aes(siteLon, siteLat))
g + annotation_raster(h_raster, lonr[1], lonr[2], latr[1], latr[2]) +
geom_point(aes(x = siteLon, y = siteLat), colour = "red", data = sites) +
scale_x_continuous(limits = lonr) +
scale_y_continuous(limits = latr)
(Sorry, I cannot post an image as I am new here).
Okay, the problem has been resolved thanks to David Kahle. See this post:
https://groups.google.com/forum/?hl=en&fromgroups#!topic/ggplot2/ABffHL3WTpY
AJ

Resources