Numbers in map marker in Folium - folium

i want to display some geo locations on map, but i want the map-pin icon to display numbers instead of the default map pin.
Is there any way to do that?
I checked in font awesome icons but it didn't work.
Below is my code:
import folium
m = folium.Map(
location=[45.3288, -121.6625],
zoom_start=12,
#tiles='Mapbox Bright'
)
folium.Marker([45.3288, -121.6625], popup='<i>Mt. Hood Meadows</i>').add_to(m)
folium.Marker([45.3311, -121.7113], popup='<b>Timberline Lodge</b>',icon=folium.Icon(color='red')).add_to(m)
m
What i want is instead of this default map marker i want to include numbers in my marker instead of info-sign
Something like this:
i couldn't find the answer anywhere. Any leads on this?
display number 1 to 9 inside map marker pin

I was attempting something similar on a recent project and this is what I came up with. Might work for you.
It plots a DivCon marker with html and then a transparent circle marker in the same location.
import folium
from folium.features import DivIcon
m = folium.Map(
location=[45.3288, -121.6625],
zoom_start=12,
#tiles='Mapbox Bright'
)
p1 = [45.3288, -121.6625]
folium.Marker(p1, icon=DivIcon(
icon_size=(150,36),
icon_anchor=(7,20),
html='<div style="font-size: 18pt; color : black">1</div>',
)).add_to(m)
m.add_child(folium.CircleMarker(p1, radius=15))
p2 = [45.3311, -121.7113]
folium.Marker(p2, icon=DivIcon(
icon_size=(150,36),
icon_anchor=(7,20),
html='<div style="font-size: 18pt; color : black">2</div>',
)).add_to(m)
m.add_child(folium.CircleMarker(p2, radius=15))

Adapting the previous answer by #bob I found a solution that fit my needs. I put it below in case it is useful for anyone:
import folium
from folium.features import DivIcon
def number_DivIcon(color,number):
""" Create a 'numbered' icon
"""
icon = DivIcon(
icon_size=(150,36),
icon_anchor=(14,40),
# html='<div style="font-size: 18pt; align:center, color : black">' + '{:02d}'.format(num+1) + '</div>',
html="""<span class="fa-stack " style="font-size: 12pt" >>
<!-- The icon that will wrap the number -->
<span class="fa fa-circle-o fa-stack-2x" style="color : {:s}"></span>
<!-- a strong element with the custom content, in this case a number -->
<strong class="fa-stack-1x">
{:02d}
</strong>
</span>""".format(color,number)
)
return icon
col_hex = ['#440154',
'#481a6c',
'#472f7d',
'#414487',
'#39568c',
'#31688e',
'#2a788e',
'#23888e',
'#1f988b',
'#22a884',
'#35b779',
'#54c568',
'#7ad151',
'#a5db36',
'#d2e21b']
num = 0
loc = (43.613, 3.888)
fm = folium.Map(location=loc, tiles="Stamen Terrain")
folium.Marker(
location=loc,
popup="Delivery " + '{:02d}'.format(num+1),
icon=folium.Icon(color='white',icon_color='white'),
markerColor=col_hex[num],
).add_to(fm)
folium.Marker(
location=loc,
popup="Delivery " + '{:02d}'.format(num+1),
icon= number_DivIcon(col_hex[num],num+1)
).add_to(fm)
fm

I need these numbers (1,2) to be dynamic, meaning, I have a for loop, I want index value to be printed in the HTML line
for point in range(0, len(coordinates_st)):
# showing number
folium.Marker(location=[72.89, -124.59+2], icon=DivIcon(
icon_size=(150, 36),
icon_anchor=(7, 20),
html='<div style="font-size: 18pt; color : black">r{point}</div>',
)).add_to(map_st)

Related

Shiny R Selectize Input widget size target the input

I have multiple selectizeInput in my Shiny app. Most of them are not supposed to be full of variables/elements, but one of them yes. The problem is the more variables/elements in the box, the larger is this one and the display is not good at all. I have found solutions to manipulate the height, font, width, etc. of a input widget:
library(shiny)
ui <- fluidPage(
fluidRow(
selectInput("speed", label=NULL, choices = list("1" = 1, "2" = 2), selected = 1),
tags$head(tags$style(HTML(".selectize-input {height: 100px; width: 500px; font-size: 100px;}")))
)
)
server <- function(input, output){}
shinyApp(ui, server)
This works. But this solution affects to all the selectizeInput I have in my app, I'm interested in just target one selectizeInput. Is there a way to do that?
You can use some advanced CSS to select the .selectize-input box. So in selectInput structure, the element with the actual id is assigned to a select tag and the box you want is the first child of the following tag after the select tag. We can use + to select the following tag and use > to select the first child containing the .selectize-input class of the following tag.
library(shiny)
ui <- fluidPage(
tags$head(tags$style(HTML("#speed + div > .selectize-input {height: 100px; width: 500px; font-size: 100px;}"))),
fluidRow(
selectInput("speed", label=NULL, choices = list("1" = 1, "2" = 2), selected = 1),
selectInput("speed2", label=NULL, choices = list("1" = 1, "2" = 2), selected = 1)
)
)
server <- function(input, output){}
shinyApp(ui, server)
#ID + div > .selectize-input is what you want to apply.
Try to run my example, I created two selectInput and only the first one will have the CSS style.

beautifulsoup: get text (including html tags) between two different tags (</h3> and <h2>)

I am trying to scrape an html file structured as follow using beautifulsoup. Basicaly, each unit is constisted of:
one <h2></h2>
one <h3></h3>
more than one <p></p>
Something like follow:
<h2>January, 2020</h2>
<h3>facility</h3>
<p>text1-1</p>
<p>text1-2</p>
<h2>April, 2020</h2>
<h3>scientists</h3>
<p>text2-1</p>
<p>text2-2</p>
<h2>June, 2020</h2>
<h3>lawyers</h3>
<p>text3-1</p>
<h2>.....
I want to get text including the <p> tags between </h3> and the next <h2>. The result should be:
for row #1:
<p>text1-1</p>
<p>text1-2</p>
for row #2:
<p>text2-1</p>
<p>text2-2</p>
for row #3:
<p>text3-1</p>
Here is what I tried so far:
num_h2 = len(soup.find_all('h2'))
for i in range(0,num_h2):
print('---------')
print(i)
p_string = ''
sibling = soup.find_all('h3')[i].find_next_sibling('p').getText()
if sibling:
p_string += sibling
else:
break
print(p_string)
The problem with this solution is that it only shows the content of the first <p> under each unit. I do not know how to find how many <p> are there to generate a for loop. Also, is there a better way to do this than using find_next_silibing()?
Maybe css selectors can help:
for s in soup.select('h3'):
for ns in (s.fetchNextSiblings()):
if ns.name == "h2":
break
else:
if ns.name == "p":
print(ns)
Output:
<p>text1-1</p>
<p>text1-2</p>
<p>text2-1</p>
<p>text2-2</p>
<p>text3-1</p>

beautifulsoup: find elements after certain element, not necessarily siblings or children

Example html:
<div>
<p>p1</p>
<p>p2</p>
<p>p3<span id="target">starting from here</span></p>
<p>p4</p>
</div>
<div>
<p>p5</p>
<p>p6</p>
</div>
<p>p7</p>
I want to search for <p>s but only if its position is after span#target.
It should return p4, p5, p6 and p7 in the above example.
I tried to get all <p>s first then filter, but then I don't know how do I judge if an element is after span#target or not, either.
You can do this by using the find_all_next function in beautifulsoup.
from bs4 import BeautifulSoup
doc = # Read the HTML here
# Parse the HTML
soup = BeautifulSoup(doc, 'html.parser')
# Select the first element you want to use as the reference
span = soup.select("span#target")[0]
# Find all elements after the `span` element that have the tag - p
print(span.find_all_next("p"))
The above snippet will result in
[<p>p4</p>, <p>p5</p>, <p>p6</p>, <p>p7</p>]
Edit: As per the request to compare position below by OP-
If you want to compare position of 2 elements, you'll have to rely on sourceline and sourcepos provided by the html.parser and html5lib parsing options.
First off, store the sourceline and/or sourcepos of your reference element in a variable.
span_srcline = span.sourceline
span_srcpos = span.sourcepos
(you don't actually have to store them though, you can just do span.sourcepos directly as long as you have the span stored)
Now iterate through the result of find_all_next and compare the values-
for tag in span.find_all_next("p"):
print(f'line diff: {tag.sourceline - span_srcline}, pos diff: {tag.sourcepos - span_srcpos}, tag: {tag}')
You're most likely interested in line numbers though, as the sourcepos denotes the position on a line.
However, sourceline and sourcepos mean slightly different things for each parser. Check the docs for that info
Try this
html_doc = """
<div>
<p>p1</p>
<p>p2</p>
<p>p3<span id="target">starting from here</span></p>
<p>p4</p>
</div>
<div>
<p>p5</p>
<p>p6</p>
</div>
<p>p7</p>
"""
from bs4 import BeautifulSoup
soup = BeautifulSoup(html_doc, 'html.parser')
print(soup.find(id="target").findNext('p').contents[0])
Result
p4
try
span = soup.select("span > #target > p")

R markdown: simplify creating tables of figures and text

For R markdown Rmd web pages I want to generate tables containing in the first column thumbnail images (that link to a larger image or a web site) and
descriptive text in the 2nd column. One example is the following image:
I know I can create this manually in raw HTML, but that is very fiddly and time-consuming. There must be some easier way.
On a different page, I tried a markdown / pandoc table, but that didn't work, and I reverted to manual coding of HTML
icon | title
--------------------------------------------------+--------------------------
<img src="images/books/R-Graphics.jpg" height=50> |Paul Murrell, *R Graphics*, 2nd Ed.
<img src="images/books/R-graphics-cookbook.jpg" height=50> | Winston Chang, R Graphics Cookbook
<img src="images/books/lattice.png" height=50> | Deepayan Sarkar, *lattice*
<img src="images/books/ggplot2.jpg" height=50> | Hadley Wickham, *ggplot2*
Perhaps the htmltools package would be useful here, but I can't quite see how to use it in my Rmd files for this application.
Probably forgot escaping quotes? This works fine for me:
---
title: "The Mighty Doge"
output: html_document
---
```{r}
library(knitr)
create_thumbnail <- function(file) {
paste0("<img src=\"", file, "\" style=\"width: 50px;\"/>")
}
df <- data.frame(Image = rep("unnamed.png", 5),
Description = rep("Doge", 5))
df$Image <- create_thumbnail(df$Image)
kable(df)
```
Here is an approach that uses htmltools and seems much more flexible, in that I can control the details somewhat more easily.
I'm not familiar with bootstrap <div> constructs, so I used HTML table constructs. I had to define functions for tr(), td() etc.
```{r html-setup, echo=FALSE}
library(htmltools)
# table tags
tab <- function (...)
tags$table(...)
td <- function (...)
tags$td(...)
tr <- function (...)
tags$tr(...)
# an <a> tag with href as the text to be displayed
aself <- function (href, ...)
a(href, href=href, ...)
```
Then functions to construct my table entries the way I wanted:
```{r table-functions, echo=FALSE}
# thumnail figure with href in a table column
tabfig <- function(name, img, href, width) {
td(
a(class = "thumbnail", title = name, href = href,
img(src = img, width=width)
)
)
}
tabtxt <- function(text, ...) {
td(text, ...)
}
```
Finally, use them to input the entries:
## Blogs
```{r do-blogs, echo=FALSE}
width="160px"
tab(
tr(
tabfig("FlowingData", "images/blogs/flowingdata.png", "http://flowingdata.com/", width=width),
tabtxt("Nathan Yau,", aself("flowingdata.com/"),
"A large number of blog posts illustrating data visualization methods with tutorials on how do do these with R and other software.")
),
tr(
tabfig("Junk Charts", "images/blogs/junkcharts.png", "http://junkcharts.typepad.com/", width=width),
tabtxt("Kaiser Fung,", aself("http://junkcharts.typepad.com/"),
"Fung discusses a variety of data displays and how they can be improved.")
),
tr(
tabfig("Data Stories", "images/blogs/datastories.png", "http://datastori.es/", width=width),
tabtxt("A podcast on data visualization with Enrico Bertini and Moritz Stefaner,",
aself("http://datastori.es/"),
"Interviews with over 100 graphic designers & developers.")
)
)
```
I still need to tweak the padding, but this gives me more or less what I was after:

Extract text from p only if preceding header exists using Beautifulsoup

I want to extract the text in paragraph element using beautifulsoup.
The html looks something like this:
<span class="span_class>
<h1>heading1</h1>
<p>para1</p>
<h1>heading 2</h1>
<p>para2</p>
</span>
I want to extract text from first p only if h1 exists and so on;
So far i have tried
x=soup.findAll('span',{'class':'span_class'})
y=x.findAll('p')[0].text
But i am not getting it.
You can use CSS sibling selector here:
paragraphs = x.select('h1 + p')
# `paragraphs` now contains two elements: <p>para1</p> and <p>para2</p>
This will select only those P elements that have immediate H1 siblings before them.
If you want to do some more logic based on H1 content, you can do this:
for p x.select('h1:first-child + p'):
# `p` contains the element that has `H1` before it.
# `p.previous_sibling` contains `H1`.
if p.previous_sibling.text == 'heading1':
# We got the `P` that has `H1` with content `"heading1"` before it.
print(p, p.previous_sibling)
html = '''<html>
<body>
<span class='span_class'>
<h1>heading1</h1>
<p>content1</p>
<p>content2</p>
<h1>heading2</h1>
<p>content3</p>
</span>
</body>
</html>'''
soup = bs(html, 'lxml')
x = soup.find_all('span',{'class':'span_class'}) #find span
try:
for y in x:
heading = y.find_all('h1') # find h1
for something in heading: # if h1 exist
if something.text == 'heading1':
print(something.text) # print h1
try:
p = something.find_next('p') #try find next p
print(p)
except: # if no next <p>, do nothing
pass
else:
pass #if is is not 'heading1', do nothing
except Exception as e:
print(e)
Is this what you are looking for? It will try to look for your <span> and try to find <h1> from it. For <h1> is in <span> , it will look for the next <p>.