Hi i'm trying to learn how to use a leaflet map on shiny, I used that example :
http://glimmer.rstudio.com/jcheng/leaflet-demo/
Here is the code repository :
https://github.com/jcheng5/leaflet-shiny/blob/master/inst/example/
I'm would like to replace circles by markers by replacing the addCircle function by addMarker.
The actual function is :
(line 98 of Server.R)
map$addCircle(
cities$Lat,
cities$Long,
sqrt(cities[[popCol()]]) * radiusFactor / max(5, input$map_zoom)^2,
row.names(cities),
list(
weight=1.2,
fill=TRUE,
color='#4A9'
)
)
And I just replaced it by :
map$addMarker(
cities$Lat,
cities$Long,
row.names(cities)
)
But it only plot the marker on the first city of the data frame. And after if you move and zoom randomly on the map some other markers can appear...
Why addCircle draws a circle for each cities and addMarker behaves "randomly" ?
How can I draw severals marker at once on the plot ?
The loop bellow works but ideally I don't want to loop manually if it's possible.
for(i in 1:nrow(cities)){
map$addMarker(
cities$Lat[i],
cities$Long[i],
i
)
}
Thank you
I had the same problem, it is because you remove the radius. By looking at the code for the function createLeafletMap, we can see that addCircle needs these arguments:
addCircle(lat, lng, radius, layerId = NULL, options=list(), eachOptions=list())
it really need radius. to solve your problem just write:
map$addMarker(
cities$Lat,
cities$Long,
100,
row.names(cities)
)
Related
I'm using VegaLite and VegaDatasets to show a Mercator projection of the world map, and plot a point at a specific latitude and longitude. So far, this works to produce the map:
data = DataFrame(x=[-45], y=[35])
scale = 100
world = dataset("world-110m")
#vlplot(width=700, height=500,
config={
view={stroke=:transparent}
}
) +
#vlplot(data={values=world,
format={type=:topojson,
feature="countries",
}},
mark={type=:geoshape,
stroke=:darkgray,
strokeWidth=1},
projection={type=:mercator,
scale=scale,
center=[0,35]},
color={value="#eee"}
)
producing
However, when I try to plot the point in the dataframe "data", I'm trying to set the domain in X and Y directions to (-180,180) and (-90,90), respectively:
+ #vlplot(data=data,
:point,
x = {:x, scale = {domain = (-180,180)}},
y = {:y, scale = {domain = (-90,90)}},
)
resulting in the following plot, where the domains are not at the edge of the horizontal and vertical axis. Additionally, the point seems to be plotted incorrectly within the defined grid:
Using the #vlplot syntax, how can I properly set up a latitude/longitude grid on my map, and plot a single point?
For plotting geoshape and geopoint in VegaLite, you should specify the coordinate by longitude and latitude. So your last code should be (projection should be included):
+ #vlplot(data=data,
:point,
longitude = :x,
latitude = :y,
projection={type=:mercator,
scale=scale,
center=[0,35]}
)
I'm trying to create a map displaying some restaurants in their locations in a Jupyter Notebook and folium. Also, the restaurants are assigned with different categories. I want to assign a different color for each category.
I add the code I have so far.
df_unicos is a pandas dataframe containing all the different categories of restaurants available (i.e 15, 0 to 14). If I comment (#) the lines containing the 'mo' variable it works but all the markers have the same color.
rangocolores=len(target['Venue Category'].unique())
# create map of the restaurants of Terrassa using latitude and longitude values
map_restaurants = folium.Map(location=[latitude, longitude], zoom_start=14)
#set color scheme for the clusters
x = np.arange(rangocolores)
ys = [i + x + (i*x)**2 for i in range(rangocolores)]
colors_array = cm.rainbow(np.linspace(0, 1, len(ys)))
rainbow = [colors.rgb2hex(i) for i in colors_array]
# add markers to the map
markers_colors = []
mo=0
for lat, lng, venu, barri in zip(target['Venue Latitude'], target['Venue Longitude'], target['Venue Category'], target['Neighborhood']):
mo=df_unicos[df_unicos['Restaurante'].str.contains(venu)].index.item()
label = '{},{}'.format(venu, barri)
label = folium.Popup(label, parse_html=True)
folium.CircleMarker(
[lat, lng],
radius=5,
popup=label,
color=rainbow[mo],
fill=True,
fill_color=rainbow[mo],
fill_opacity=0.7).add_to(map_restaurants)
map_restaurants
I get the following error:
ValueError: can only convert an array of size 1 to a Python scalar
It points to the line:
mo=df_unicos[df_unicos['Restaurante'].str.contains(venu)].index.item()
any help will be appreciated, thanks a lot!
Arturo
I'm so new in python...
Changing
.str.contains()
to
.str.match()
solved the issue.
I am new to geo-mapping and wanted to produce a hexagonal heatmap over a geographic map of Canada.
I have latiude and longitude within my original data set, and I even have a variable I wish to use to produce the "heat" of each hexagonal tile placed on the map, but I am encountering 2 problems.
1) it appears as if there is a vertical translation applied to each coordinate.
2) I do not know how to show "heat" of another variable and not show density for the heatmap.
My data is given as follows:
map<-get_map(location='Canada', zoom=3, maptype = "terrain",
source='google',color='color')
dat<-data.frame(cbind(c(47.00735, 47.36228, 47.40399, 48.08666,47.57196, 47.63742),
c(-52.95892, -53.29399, -52.79987, -52.89429, -53.27813, -52.92653),
c(86301.14, 1017390.34, 2662332.67, 473139.73, 8251899.99, 167512.52)))
names(dat)<-c('Longitude','Latitude','Rating')
Now the interesting thing is, when I run the following code, I get a hexagonal heat map with respect to density:
ggplot(dat, aes(x=Longitude,y=Latitude,color=Rating))+
stat_binhex(na.rm=TRUE)+
scale_fill_gradientn(colours=c("red","blue"),na.value=NA)
I get this output:
What I would like is a hexagonal heatmap where heat is shown by the Rating field.
Next, when I add a google map layer with the following code:
ggmap(map) +
ggplot(dat, aes(x=Longitude,y=Latitude,color=Rating))+
stat_binhex(na.rm=TRUE)+
scale_fill_gradientn(colours=c("red","blue"),na.value=NA)
I get the following error: Error: Don't know how to add o to a plot
If anyone know hows to remedy these issues, it would be greatly appreciated. Thank you!
I am using the leaflet package for R to plot circles in sizes and colors that are determined by a set of variables. It works well, but not all circles can be selected with the cursor. I cannot show the mouseover tooltip or popup window for circles that are hidden underneath larger circles.
How can I fix that? I already have on/off toggles in my legend to simplify the map and hide categories, but the issue persist when overlapping circles belong to the same category.
A drag-n-drop feature, or a way to cycle through circles under the cursor using the mouse wheel would be perfect, but I am not sure this can be achieved in R.
Thank you.
[Edit] Here is an example:
library(leaflet)
n <- c(50, 100)
coord <- matrix(c(-72.3, -70.3, -72, -70), nrow=2, byrow=T)
map <- leaflet() %>%
addTiles() %>%
setView(lng = -72, lat = -70, zoom = 5)
for (i in 1:length(n)) {
map <- map %>% addCircles(lng = coord[i, 1], lat = coord[i, 2], radius = n[i]*1000, # Radius is proportional to sample size
label=paste0("Mouseover tooltip ", i),
popup=paste0("Popup window ", i),
highlightOptions=highlightOptions(color="black", weight=2))
}
map
Output with circle 2 preventing selection of circle 1 because it is on top:
Radius is a function of sample size in the data set, so I cannot freely manipulate it to avoid overlapping, and cannot reduce it an all circles either because I already have very small samples in the data set. Blue would be one category here (other categories/colors exist in the data set but can toggled off from the legend so it's not an issue when they hide other categories). The circle 1 is smaller than the circle 2 due to a smaller sample.
Of course, here I drew the only two circles using addCircles twice, so I could just decide to plot the smaller circle after the larger one so it's on the top layer. But in my data, there are tens of circles plotted automatically according to the variables and I cannot sort manually the order in which circles from a single category are plotted.
[Edit 2] Just found out that adding sendToBack=T to the highlightOptions=highlightOptions()line helps. It allows cycling through overlapping circles by sending those on the front to the back after they have been hovered by the cursor. However it's not perfect when there are more than 2 circles, because the user would hardly cycle voluntarily using this method, the cursor has to be brought in and out several times until the correct circle is highlighted. Better than nothing though. If anyone has another method to suggest, please don't hesitate.
I'm trying to plot flat maps in RGL's 3d environment because it should enable maps to be custom zoomed/tilted for a projection that best suits both the data and required output image aspect. This thread describes the process for plotting images using rgl.surface(). But its not clear if this method is adaptable for OSM/other map objects. Very grateful for any ideas you may have.
This is the starting point, which fails because Error in is.matrix(z) : 'z' is missing. Any idea how I can insert some zeros for z coordinates?
require(rgl)
open3d() # R crashes if this is done later(?)
#Sys.setenv(NOAWT=1) # fix an {OSM} X11 issue in Mac
require(OpenStreetMap)
require(ggplot2)
lat <- c(53, 50); lon <- c(-5, 1)
map <- openmap(c(lat[1],lon[1]),c(lat[2],lon[2]), 5, 'osm')
map <- openproj(map)
rgl.surface(map)
You need to create a matrix of zeroes for heights and use the col= argument to surface3d to set the colour of the image.
Getting all the dimensions and ordering and all that out of the map object is a faff, so here's a function to do it:
map3d <- function(map,...){
if(length(map$tiles)!=1){
stop("multiple tiles not implemented")
}
nx = map$tiles[[1]]$xres
ny = map$tiles[[1]]$yres
xmin = map$tiles[[1]]$bbox$p1[1]
xmax = map$tiles[[1]]$bbox$p2[1]
ymin = map$tiles[[1]]$bbox$p1[2]
ymax = map$tiles[[1]]$bbox$p2[2]
xc = seq(xmin,xmax,len=ny)
yc = seq(ymin,ymax,len=nx)
colours = matrix(map$tiles[[1]]$colorData,ny,nx)
m = matrix(0,ny,nx)
surface3d(xc,yc,m,col=colours,...)
}
Which gives us:
Now, note it only works if there's one tile in the returned map, but the principle is there.
Also, I'm not totally convinced the coordinate alignment is exact. The coordinates may be centre of pixels or edges of the image, so maybe there's a +1 missing somewhere. And I'm not sure if it applies to the gray border or not.