I want to add text on the lines added using Polyline from within the folium library.(etc "1km" or "1ft")
m = folium.Map(location=[41.08468198029149, 28.8180159802915])
points = [[41.0370023, 28.9850917], [40.98186700000001, 29.0576302]]
for point in points:
folium.Marker(point).add_to(m)
folium.PolyLine(points, color="red", weight=2.5, opacity=1).add_to(m)
Something like that
[EDIT]
I find it!
Check it out
line = folium.PolyLine(points, color="red", weight=2.5, opacity=1)
attr = {'fill': '#007DEF', 'font-weight': 'bold', 'font-size': '24'}
wind_textpath = plugins.PolyLineTextPath(line,
"20 km",
center=True,
offset=7,
attributes=attr)
m.add_child(line)
m.add_child(wind_textpath)
Related
I'm new in using plotly and I'm trying to make a 2 different graph and show them individually through button; however, when I make it, the legends duplicated, resulting to a bad visualization of the data. Here's the code that I'm running right now:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import plotly as ply
import plotly.express as px
import plotly.graph_objects as go
url = "https://raw.githubusercontent.com/m23chaffee/DS100-Repository/main/Aluminum%20Alloy%20Data%20Set.csv"
alloy = pd.read_csv('https://raw.githubusercontent.com/m23chaffee/DS100-Repository/main/Aluminum%20Alloy%20Data%20Set.csv')
del alloy['temper']
alloy = alloy.rename(columns={'aluminum_alloy':'Alloy Number',
'modulus_elastic': 'Elastic Modulus',
'modulus_shear': 'Shear Modulus',
'strength_yield': 'Yield Strength',
'strength_tensile': 'Tensile Strength'
})
bar1 = px.bar(alloy,
x = "Alloy Number",
y = ["Elastic Modulus", "Shear Modulus","Yield Strength","Tensile Strength"],
barmode = 'group',
width = 1100,
height =500,
orientation = 'v',
color_discrete_sequence = px.colors.qualitative.Pastel,
labels={"value": "Data Values"},
template = 'seaborn').update_traces(legendgroup="group").update_layout(showlegend=False)
line1 = px.line(alloy,
x = "Alloy Number",
y = ["Elastic Modulus", "Shear Modulus","Yield Strength","Tensile Strength"],
width = 1100,
height =500,
orientation = 'v',
color_discrete_sequence = px.colors.qualitative.Pastel,
labels={"value": "Data Values"},
template = 'seaborn').update_traces(legendgroup="group", visible = 'legendonly').update_layout(showlegend=False)
# Add buttom
fig.update_layout(
updatemenus=[
dict(
type = "buttons",
direction = "left",
buttons=list([
dict(
args=['type', 'bar'],
label="Bar Graph",
method="restyle",
),
dict(
args=["type", "line"],
label="Line Graph",
method="restyle"
)
]),
pad={"r": 10, "t": 10},
showactive=True,
x=0.11,
xanchor="left",
y=1.1,
yanchor="middle"
),
]
)
fig.show()
and the result of the image would look like this:
Result of the code above
Attempted Solution
I tried to hide it using traces and in the documentation but it seems it didn't work out for me. I also found a similar stackoverflow post 8 years ago, tried it, and it didn't make any changes in my graph.
I am trying to change the symbol from circle to location pin to highlight the co-ordinates on to the map.However, apart from "circle" no other options work correctly in the symbol option.
I have tried - square,marker, triangle.Can someone tell me how to fix this, it doesnt throw an error
#Plotting co-ordinates on to the map
fig = go.Figure(go.Scattermapbox
(
lat=df["Latitude"],
lon=df["Longitude"],
mode='markers',
marker=go.scattermapbox.Marker
(
size=10,
color = df['Size'],
colorscale = 'RdYlGn_r',
showscale=True,
symbol = 'star'
)
)
Please note that markers different from "circle" (default) work only if you are using "vector tiles from the Mapbox service" (e.g. "dark" or "satellite") for which your mapbox token needs to be provided; but they don't work if you are using "open" vector tiles" like "open-street-map"
In the plotly documentation they do this using another syntax, have you tried that already?
import plotly.graph_objects as go
token = open(".mapbox_token").read() # you need your own token
fig = go.Figure(go.Scattermapbox(
mode = "markers+text+lines",
lon = [-75, -80, -50], lat = [45, 20, -20],
marker = {'size': 20, 'symbol': ["bus", "harbor", "airport"]},
text = ["Bus", "Harbor", "airport"],textposition = "bottom right"))
fig.update_layout(
mapbox = {
'accesstoken': token,
'style': "outdoors", 'zoom': 0.7},
showlegend = False)
fig.show()
Source: https://plot.ly/python/scattermapbox/#set-marker-symbols
Apparently it's impossible to set both a non-circle symbol and a marker color at once.
Note that the array marker.color and marker.size are only available
for “circle” symbols.
Source: https://plotly.com/python-api-reference/generated/plotly.graph_objects.Scattermapbox.html
I'm trying to create slider that as you drag the slider, the portion of the graph that is shown is only what is on the slider. For example, if you look at my graph below, if the slider was set to 1990, you would only see the lines from 1990 to 2016. I found a working example with plotly but I wanted to see if it could be done with Bokeh.
This is my code so far:
p = figure(width = 900, height = 450)
p.xaxis.axis_label = 'Year'
p.yaxis.axis_label = 'Aggregated Number of Degrees in Education'
source = ColumnDataSource(df)
fill_source = ColumnDataSource(data=dict(x=[],y=[]))
# Create objects for each line that will be plotted
stem = p.line('year', 'stem', line_color='#8dd3c7', line_width=3, source=source)
stem = p.circle('year', 'stem', line_color='#8dd3c7', line_width=3, source=source)
sped = p.line('year', 'sped', line_color='#fdb462', line_width=3, source=source)
elem = p.line('year', 'elem', line_color='#bebada', line_width=3, source=source)
elem = p.square('year', 'elem', line_color='#bebada', line_width=3, source=source)
other = p.line('year', 'other', line_color='#fb8072', line_width=4, source=source)
aggtotal = p.line('year', 'aggtotal', line_dash=[4,4,], line_color='#80b1d3', line_width=3, source=source)
yaxis = p.select(dict(type=Axis, layout="left"))[0]
yaxis.formatter.use_scientific = False
legend = Legend(items=[("STEM", [stem])
,("SPED" , [sped])
,("Elementary", [elem])
,("Other", [other])
,("Total Education Graduates", [aggtotal])], location=(0, 0))
p.add_tools(HoverTool(tooltips=[("Date", "#year")]))
p.add_layout(legend, 'right')
callback_test = CustomJS(args=dict(source=source,fill_source=fill_source), code="""
var data = source.data;
var fill_data = fill_source.data;
var s_val = cb_obj.value;
fill_data['x']=[];
fill_data['y']=[];
for (i = 0; i < s_val; i++) {
fill_data['y'][i].push(data['y'][i]);
fill_data['x'][i].push(data['x'][i]);
}
fill_source.trigger('change');
""")
sped_slider = Slider(start=1984, end= 2016, value=1, step=1,title="Year",callback=callback_test)
callback_test.args["sped"] = sped_slider
layout = row(p,widgetbox(sped_slider))
This renders a slider but it doesn't do anything and I'm not sure where to go from here.
There are some issues with your callback code. For example:
you loop i from 0 to s_val (which may be 1990) which is not consistent with the length of your arrays.
your glyphs references columns 'stem', etc... but the fill_source has columns 'x' and 'y'
your glyphs reference source as a source but you change and trigger event on fill_source.
All that could probably be fixed but there's a much easier way, adjust the range in the callback. E.g. replace your callback by this:
x_range = p.x_range
callback_test = CustomJS(args=dict(x_range=x_range), code="""
var start = cb_obj.value;
x_range.start = start;
x_range.change.emit();
""")
Note the change to the event trigger. Your version would work but I think it's going to be deprecated.
Also:
this line callback_test.args["sped"] = sped_slider is not necessary
you could add toolbar_location='above' in figure(...) to avoid rendering conflict with the legend
you're still going to have a layout problem between the slider and the legend which can be fixed in different ways (slider under or put the slider and the legend in a column before adding to the right of the plot, etc...)
I have created a histogram in bokeh using the following code:
TOOLS="pan,wheel_zoom,box_zoom,reset,hover"
for column in valid_columns:
output_file_name = str( file_name + column + ".html" )
data_values = stats[ column ].tolist()
output_file( output_file_name )
histogram, edges = np.histogram( data_values, bins=50 )
source = ColumnDataSource(
data = dict( data_value = data_values ) )
p1 = figure( title = column, background_fill="#E8DDCB", tools=TOOLS )
p1.quad( top = histogram, bottom = 0, left = edges[ :-1 ], right = edges[ 1: ],
fill_color = "#036564", line_color = "#033649" )
hover = p1.select(dict(type=HoverTool))
hover.tooltips = [ ( "Value", "#data_value" ) ]
show( p1 )
print( "Saved Figure to ", output_file_name )
where valid columns are a list of all columns I want examined within a pandas dataframe. I am trying to add a hover tool tip which will display the number of items stored in each bin but I have not be able to do so. Any help would be appreciated.
If you prefer to not use a ColumnDataSource, you can replace #data_value with #top and it should work with minimal editing:
hover = HoverTool(tooltips = [('Value', '#top')])
p.add_tools(hover)
i.e. editing the example histogram.py in this way also works:
from bokeh.models import HoverTool
def make_plot(title, hist, edges, x, pdf, cdf):
p = figure(title=title, tools='', background_fill_color="#fafafa")
p.quad(top=hist, bottom=0, left=edges[:-1], right=edges[1:],
fill_color="navy", line_color="white", alpha=0.5)
p.line(x, pdf, line_color="#ff8888", line_width=4, alpha=0.7, legend_label="PDF")
p.line(x, cdf, line_color="orange", line_width=2, alpha=0.7, legend_label="CDF")
p.y_range.start = 0
p.legend.location = "center_right"
p.legend.background_fill_color = "#fefefe"
p.xaxis.axis_label = 'x'
p.yaxis.axis_label = 'Pr(x)'
p.grid.grid_line_color="white"
hover = HoverTool(tooltips = [('Density', '#top')])
p.add_tools(hover)
return p
It looks like you are missing a couple of things:
Have a source of the same length as your histogram, not your data_values. To be more concrete, I think you want your source to be:
source = ColumnDataSource( data = dict( data_value = histogram ) )
Add the source to your p1.quad call, i.e.
p1.quad( top = histogram, bottom = 0, left = edges[ :-1 ], right = edges[ 1: ],
fill_color = "#036564", line_color = "#033649", source = source )
I have created the following doughnut chart in bokeh, using annular_wedge glyphs. I've created a tooltip, that shows percents & category properly for each wedge, but always includes an extra category : ??? and percents:1
Why is it appearing, and how can I remove it ?
Here's a link to the notebook used for generating the plot : link
# define starts/ends for wedges from percentages of a circle
percents = [0, 0.14, 0.22, 0.40, 0.83, 0.99, 1.0]
category = ['Extreme ', 'High ', 'Light ', 'Medium ', 'Not Classified', 'Very Light ']
starts = [p*2*pi for p in percents[:-1]]
ends = [p*2*pi for p in percents[1:]]
# a color for each pie piece
colors = brewer['Spectral'][len(percents)]
# create source
source = ColumnDataSource(
data=dict(
x=[0 for x in percents],
y=[0 for x in percents],
ymin = [0.5 for x in percents],
ymax = [1 for x in percents],
percents=percents,
category= category,
starts=starts,
colors=colors,
ends=ends,
)
)
# create chart
TOOLS = "hover"
p = bk.figure(title='Chronic',title_text_font ='Roboto', title_text_font_size ='14pt', title_text_alpha =0.7,
x_range=(-1.1,1.1), y_range=(-1.1,1.1), width=250, height=250, tools=TOOLS)
p.annular_wedge(x='x', y='y', inner_radius='ymin', outer_radius='ymax', direction="anticlock",
start_angle='starts', end_angle='ends', color='colors', source=source)
hover = p.select(dict(type=HoverTool))
hover.tooltips = [
('category', '#category'),
('percents','#percents')
]
# displays
bk.show(p)
I solved the problem by setting these values directly in the function call:
p.annular_wedge(x=0, y=0, inner_radius=0.5, outer_radius=1, ... )