How to combine two x axes using subplot - python-3.x

I have two plots (candle and bar). I want to combine them in the same subplot (x-axes in the top for volume and x-axes at the bottom for dates), but when I try to combine both in the same subplot (row=2, col=1), the result it's not the expected.
import plotly from plotly
import subplots
import random
import pandas as pd
import plotly.graph_objects as go
fig = make_subplots(rows=3, cols=2)
high = 40
low = 5
dev = 1
days = 18
fake_market = []
for each in range(days):
ohlc = []
ohlc.append(each)
if each == 0:
o = random.randrange(low, high)
ohlc.append(o)
else:
ohlc.append(c) #I know
h = random.randrange(o, high)
ohlc.append(h)
l = random.randrange(low, o)
ohlc.append(l)
c = random.randrange(l, h)
ohlc.append(c)
fake_market.append(ohlc)
fake_volume = [[x, random.randrange(1, 200)] for x in range(low, (high+1))]
df = pd.DataFrame(fake_market, columns=["Date", "Open", "High", "Low", "Close"])
df2 = pd.DataFrame(fake_volume, columns=["Volume", "Price"])
fecha = ['2019-03-22', '2019-03-23', '2019-03-24', '2019-03-25',
'2019-03-26', '2019-03-27', '2019-03-28', '2019-03-29',
'2019-03-30', '2019-03-31', '2019-04-01', '2019-04-02',
'2019-04-03', '2019-04-04', '2019-04-05', '2019-04-06',
'2019-04-07', '2019-04-08']
candle =go.Candlestick(
x=fecha,
open=[str(x) for x in df.Open.to_list()],
high=[str(x) for x in df.High.to_list()],
low=[str(x) for x in df.Low.to_list()],
close=[str(x) for x in df.Close.to_list()],
visible=True,
showlegend=True,
xaxis='x3',
yaxis ='y3')
vol_bar = go.Bar(
x=[str(x) for x in df2.Price.to_list()],
y=[str(x) for x in df2.Volume.to_list()],
xaxis='x4',
yaxis ='y4',
name='volume',
orientation="h",
opacity=0.4, marker=dict(
color='rgba(246, 78, 139, 0.6)', line=dict(color='rgba(246, 78, 139, 1.0)', width=0.1)))
fig.add_trace(candle, row=2, col=1)
fig.add_trace(vol_bar, row=2, col=1)
fig.update_layout(
yaxis3=dict(
title="yaxis3 title",
titlefont=dict(
color="#1f77b4"
),
tickfont=dict(
color="#1f77b4"
)
),
yaxis4=dict(
title="yaxis4 title", side='right',
titlefont=dict(
color="#1f77b4"
),
tickfont=dict(
color="#1f77b4"
)
),
xaxis3=dict(
title="xaxis3 volume", side='top', overlaying='x',
titlefont=dict(
color="#9467bd"
),
tickfont=dict(
color="#9467bd"
)),
xaxis4=dict(
title="xaxis4 date", side='bottom',
titlefont=dict(
color="#9467bd"
),
tickfont=dict(
color="#9467bd"
))
)
fig.update_xaxes(rangeslider_visible=False)
fig.show()
The plots are showed as follow:
The plots:
The result: The result:
The plot expected: The plot expected:
Apparently the x axes are mixing and that is the reason for getting a distorted graph is obtained.

Related

Plotly Custom Legend

I have a plotly plot which looks like this:
The Code I am using is below:
fig = make_subplots(specs=[[{"secondary_y": True}]])
fig.add_trace(go.Scatter( x = pf['Timestamp'], y = pf['Price_A'], name ='<b>A</b>',
mode = 'lines+markers',
marker_color = 'rgba(255, 0, 0, 0.8)',
line = dict(width = 3 ), yaxis = "y1"),
secondary_y=False,)
fig.add_trace(go.Scatter( x = df['Timestamp'], y = df['Price_B'], name='<b>B</b>',
mode = 'lines+markers',
marker_color = 'rgba(0, 196, 128, 0.8)',
line = dict(width = 3 ), yaxis = "y1") ,
secondary_y=False,)
for i in pf2['Timestamp']:
fig.add_vline(x=i, line_width=3, line_dash="dash", line_color="purple",
name='Event')
fig.update_layout( title="<b>Change over Time</b>", font=dict( family="Courier New,
monospace", size=16, color="RebeccaPurple"),
legend=dict(
yanchor="top",
y=0.99,
xanchor="left",
x=0.01
))
How can I add the entry in the legend for the event that is denoted by the vertical lines?
When you use add_vline, you are adding an annotation which will not have a corresponding legend entry.
You'll need to instead use go.Scatter to plot the vertical lines, passing the minimum and maximum values in your data (plus or minus some padding) to the y parameter. Then you can set this same y-range for your plot. This will give you the appearance of vertical lines while still showing the full range of your data.
Update: you can use a legend group so that the vertical lines appear as a single entry in the legend
For example:
from pkg_resources import yield_lines
import plotly.express as px
import plotly.graph_objects as go
fig = go.Figure()
df = px.data.stocks()
for col in ['GOOG','AMZN']:
fig.add_trace(go.Scatter(
x=df['date'],
y=df[col]
))
vlines = ["2018-07-01","2019-04-01","2019-07-01"]
min_y,max_y = df[['GOOG','AMZN']].min().min(), df[['GOOG','AMZN']].max().max()
padding = 0.05*(max_y-min_y)
for i,x in enumerate(vlines):
fig.add_trace(go.Scatter(
x=[x]*2,
y=[min_y-padding, max_y+padding],
mode='lines',
line=dict(color='purple', dash="dash"),
name="vertical lines",
legendgroup="vertical lines",
showlegend=True if i == 0 else False
))
fig.update_yaxes(range=[min_y-padding, max_y+padding])
fig.show()

How do I apply a line between two points in geopanda e.g. between 2 cities

I am trying to plot a green line between the 2 cities on my map in geopandas
The result should show the 2 cities with the red point and the name of the cities as well plus a green line between the two cities
I hope you can help me!
Thanks in ahead!
I tried it a few times but I dont get the key for plotting a line
import geopandas as gpd
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
###################### The Map of Germany is plotted here
plt.style.use('seaborn')
plz_shape_df = gpd.read_file(r'C:\Users\XXXXX\geopanda\plz-gebiete.shp', dtype={'plz': str})
plz_shape_df.head()
plt.rcParams['figure.figsize'] = [16, 11]
fig, ax = plt.subplots()
plz_shape_df.plot(ax=ax, color='orange', alpha=0.8)
ax.set(
title='Germany',
aspect=1.3,
facecolor='lightblue');
################ The dict: new_dict3 with the 2 cities gets plotted
new_dict3 = {
'Stuttgart': (9.181332, 48.777128),
'Munich': (11.576124, 48.137154),
}
for c in new_dict3.keys():
ax.text(
x=new_dict3[c][0],
y=float(new_dict3[c][1]) + 0.1,
s=c,
fontsize = 12,
ha = "center",
)
ax.plot(
new_dict3[c][0],
new_dict3[c][1],
marker = "o",
c = "red",
alpha = 2.0
)
############### Now I want to plot a green line between the 2 cities of the new_dict3
ax.plot(
x= new_dict3[c][0],
y= float(new_dict3[c][1]) + 0.1,
linestyle = "--",
c = "green",
marker="",
)
#this doesn't work
[
I got the right answer myself here is my result:
Stuttgart = [9.181332, 48.777128]
Munich = [11.576124, 48.137154]
x_values = [ Stuttgart[0], Munich[0]]
y_values = [ Stuttgart[1], Munich[1]]
plt.plot(x_values, y_values, linewidth = 5, linestyle = "--", color = "green")

How do I add vertical moving hover line to my plotly chart

I am trying to achieve what is done here: https://www.quantalys.com/Fonds/120955 with javascript in python plotly. I want to add the hover vertical line and the red annotation on the x axis. I have done some searching on goolgle but I couldn't find the the answer I'm looking for. My current chart looks like this:
trace1 = go.Scatter(
x = df1.x,
y = df1.y,
name = "M&G OPTIMAL INCOME FD EUR AH ACC",
hoverinfo= 'name',
opacity=0.7,
mode = 'lines',
line = dict(
color = ('rgb(2, 12, 245)'),
width = 1,
),
)
trace2 = go.Scatter(
x = df2.x,
y = df2.y,
opacity=0.7,
name = "Alloc Flexible Prudent Monde",
hoverinfo= 'name',
mode = 'lines',
line = dict(
color = ('rgb(67, 45, 24)'),
width = 1,
)
)
trace3 = go.Scatter(
x = df3.x,
y = df3.y,
name = "25% MSCI World + 75% ML Global",
hoverinfo= 'name',
mode = 'lines',
opacity=0.7,
line = dict(
color = ('rgb(205, 12, 24)'),
width = 1,
)
)
layout = go.Layout(
xaxis=dict(
showline=True,
showgrid=True,
showticklabels=True,
linecolor='rgb(204, 204, 204)',
linewidth=2,
mirror=True,
),
yaxis=dict(
showline=True,
showgrid=True,
showticklabels=True,
linecolor='rgb(204, 204, 204)',
linewidth=2,
mirror=True,
),
showlegend=True,
)
data= [trace1, trace2,trace3]
fig = dict(data=data, layout=layout)
iplot(fig, filename='line-mode')
Add this to your layout definition.
showlegend = True,
hovermode = 'x'
Add this to your xaxis definition.
showspikes = True,
spikemode = 'across',
spikesnap = 'cursor',
showline=True,
showgrid=True,
...
And add this to your layout definition:
spikedistance = -1,
xaxis=dict(...
Please refer to this post and the documentation by plotly. :)
EDIT
You ask for the x-axis lable. Please use
spikemode = 'across+toaxis'
Additionally I would suggest to use
spikedash = 'solid'
because it is better fitting your example.

Trouble with Multiple Sankey Subplots in Plotly

So I’m stuck trying to create a plot with multiple Sankey diagrams. Specifically, I keep getting an error that says "Invalid property specified for object of type plotly.graph_objs.Sankey: 'xaxis'". This seems to be invoked when the script gets to the append_trace command. Here is a simple example code, which I run in a Jupyter notebook:
import plotly.tools as tools
import plotly.offline as offline
import plotly.graph_objs as go
offline.init_notebook_mode(connected = True)
trace1 = go.Sankey(
node = dict(
pad = 15,
thickness = 20,
line = dict(
color = "black",
width = 0.5
),
label = ["Joe", "Molly", "Gavin", "Octavio", "Leslie", "Natasha"],
color = ["blue", "red", "green", "yellow", "brown", "magenta"]
),
link = dict(
source = [0,1,3],
target = [5,5,0],
value = [6,8,3]
)
)
trace2 = go.Sankey(
node = dict(
pad = 15,
thickness = 20,
line = dict(
color = "black",
width = 0.5
),
label = ["Russia", "Gambia", "Sweden", "Bolivia", "Timor-Leste", "Kazakhstan", "Bhutan"],
color = ["red", "black", "brown", "magenta", "yellow", "blue", "orange"]
),
link = dict(
source = [0,1,4,6],
target = [7,7,7,3],
value = [6,8,3,3]
)
)
fig = tools.make_subplots(rows = 2, cols = 1)
fig.append_trace(trace1, 1, 1)
fig.append_trace(trace2, 2, 1)
fig['layout'].update(
title = "Basic Sankey Diagram with Two Subplots",
font = dict(
size = 10
)
)
offline.iplot(fig)
When I run it, I get the following traceback:
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-4-dd6268edf7ab> in <module>
37 fig = tools.make_subplots(rows = 2, cols = 1)
38
---> 39 fig.append_trace(trace1, 1, 1)
40 fig.append_trace(trace2, 2, 1)
41
/anaconda3/lib/python3.7/site-packages/plotly/basedatatypes.py in append_trace(self, trace, row, col)
1222 """, DeprecationWarning)
1223
-> 1224 self.add_trace(trace=trace, row=row, col=col)
1225
1226 def _set_trace_grid_position(self, trace, row, col):
/anaconda3/lib/python3.7/site-packages/plotly/basedatatypes.py in add_trace(self, trace, row, col)
1069 return self.add_traces(data=[trace],
1070 rows=[row] if row is not None else None,
-> 1071 cols=[col] if col is not None else None
1072 )[0]
1073
/anaconda3/lib/python3.7/site-packages/plotly/basedatatypes.py in add_traces(self, data, rows, cols)
1152 if rows is not None:
1153 for trace, row, col in zip(data, rows, cols):
-> 1154 self._set_trace_grid_position(trace, row, col)
1155
1156 # Make deep copy of trace data (Optimize later if needed)
/anaconda3/lib/python3.7/site-packages/plotly/basedatatypes.py in _set_trace_grid_position(self, trace, row, col)
1259 "An axis object for ({r},{c}) subplot "
1260 "cell got deleted.".format(r=row, c=col))
-> 1261 trace['xaxis'] = ref[0]
1262 trace['yaxis'] = ref[1]
1263
/anaconda3/lib/python3.7/site-packages/plotly/basedatatypes.py in __setitem__(self, prop, value)
2823 # ### Validate prop ###
2824 if prop not in self._validators:
-> 2825 self._raise_on_invalid_property_error(prop)
2826
2827 # ### Get validator for this property ###
/anaconda3/lib/python3.7/site-packages/plotly/basedatatypes.py in _raise_on_invalid_property_error(self, *args)
3006 full_obj_name=full_obj_name,
3007 invalid_str=invalid_str,
-> 3008 prop_descriptions=self._prop_descriptions))
3009
3010 def update(self, dict1=None, **kwargs):
ValueError: Invalid property specified for object of type plotly.graph_objs.Sankey: 'xaxis'
I am NOT specifying xaxis in my traces, so where the hell is this coming from? Seems like this part may have something to do with it:
/anaconda3/lib/python3.7/site-packages/plotly/basedatatypes.py in _set_trace_grid_position(self, trace, row, col)
1259 "An axis object for ({r},{c}) subplot "
1260 "cell got deleted.".format(r=row, c=col))
-> 1261 trace['xaxis'] = ref[0]
1262 trace['yaxis'] = ref[1]
1263
Is this a bug? I have no idea.
Somebody help!
I cross-posted this question on Plotly community forums here and received an answer that solved it (mostly). I'll copy the answer here so it's preserved even if the link goes dead.
The trouble you’re running into is that make_subplots and append_trace only work for cartesian trace types right now. This is something we’re planning to improve for version 4, but in the meantime, the best approach is to specify the position of each sankey trace individually using the domain property.
import plotly.offline as offline
import plotly.graph_objs as go
offline.init_notebook_mode(connected = True)
trace1 = go.Sankey(
node = dict(
pad = 15,
thickness = 20,
line = dict(
color = "black",
width = 0.5
),
label = ["Joe", "Molly", "Gavin", "Octavio", "Leslie", "Natasha"],
color = ["blue", "red", "green", "yellow", "brown", "magenta"]
),
link = dict(
source = [0,1,3],
target = [5,5,0],
value = [6,8,3]
),
domain={
'x': [0, 0.45]
}
)
trace2 = go.Sankey(
node = dict(
pad = 15,
thickness = 20,
line = dict(
color = "black",
width = 0.5
),
label = ["Russia", "Gambia", "Sweden", "Bolivia", "Timor-Leste", "Canada", "Bhutan"],
color = ["red", "black", "brown", "magenta", "yellow", "blue", "orange"]
),
link = dict(
source = [0,1,4,6],
target = [7,7,7,3],
value = [6,8,3,3]
),
domain={
'x': [0.55, 1.0]
}
)
data = [trace1, trace2]
layout = go.Layout(
title = "Basic Sankey Diagram",
font = dict(
size = 10
)
)
fig = go.Figure(data=data, layout=layout)
iplot(fig)
This produces two subplots side by side:
Sankey subplots horizontal
Instead of specifying 'x' in domain, we can specify 'y' to position the subplots vertically.
It's a nice hack, absent the built-in support for Sankey subplots. The only drawback is that I cannot see how one would specify individual titles for the subplots.
Try this way without append operation:
Add this to the definition of both traces.
type='sankey',
Define your two subplots as data array.
data = Data([trace1, trace2])
Define fig:
fig = dict(data=[data], layout=layout)
py.iplot(fig, validate=False)
Finally you need to add the definition of your layout using a dictionary as shown in my referenced post.

How can I use the plotly dropdown menu feature to update the z value in my choropleth map?

I just want to create a menu on the plot where I'm able to change the z-value in data only. I tried looking at other examples on here: https://plot.ly/python/dropdowns/#restyle-dropdown but it was hard since the examples were not exactly similar to my plot.
import plotly
import plotly.plotly as py
import plotly.graph_objs as go
import pandas as pd
df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/2014_world_gdp_with_codes.csv')
data = [go.Choropleth(
locations = df['CODE'],
z = df['GDP (BILLIONS)'],
text = df['COUNTRY'],
colorscale = [
[0, "rgb(5, 10, 172)"],
[0.35, "rgb(40, 60, 190)"],
[0.5, "rgb(70, 100, 245)"],
[0.6, "rgb(90, 120, 245)"],
[0.7, "rgb(106, 137, 247)"],
[1, "rgb(220, 220, 220)"]
],
autocolorscale = False,
reversescale = True,
marker = go.choropleth.Marker(
line = go.choropleth.marker.Line(
color = 'rgb(180,180,180)',
width = 0.5
)),
colorbar = go.choropleth.ColorBar(
tickprefix = '$',
title = 'GDP<br>Billions US$'),
)]
layout = go.Layout(
title = go.layout.Title(
text = '2014 Global GDP'
),
geo = go.layout.Geo(
showframe = False,
showcoastlines = False,
projection = go.layout.geo.Projection(
type = 'equirectangular'
)
),
annotations = [go.layout.Annotation(
x = 0.55,
y = 0.1,
xref = 'paper',
yref = 'paper',
text = 'Source: <a href="https://www.cia.gov/library/publications/the-world-factbook/fields/2195.html">\
CIA World Factbook</a>',
showarrow = False
)]
)
fig = go.Figure(data = data, layout = layout)
py.iplot(fig, filename = 'd3-world-map')
It's been a while since this was asked, but I figured it was still worth answering. I can't speak to how this might have changed since it was asked in 2019, but this works today.
First, I'll provide the code I used to create the new z values and the dropdown menu, then I'll provide all of the code I used to create these graphs in one chunk (easier to cut and paste...and all that).
This is the data I used for the alternate data in the z field.
import plotly.graph_objects as go
import pandas as pd
import random
z2 = df['GDP (BILLIONS)'] * .667 + 12
random.seed(21)
random.shuffle(z2)
df['z2'] = z2 # example as another column in df
print(df.head()) # validate as expected
z3 = df['GDP (BILLIONS)'] * .2 + 1000
random.seed(231)
random.shuffle(z3) # example as a series outside of df
z4 = df['GDP (BILLIONS)']**(1/3) * df['GDP (BILLIONS)']**(1/2)
random.seed(23)
random.shuffle(z4)
z4 = z4.tolist() # example as a basic Python list
To add buttons to change z, you'll add updatemenus to your layout. Each dict() is a separate dropdown option. At a minimum, each button requires a method, a label, and args. These represent what is changing (method for data, layout, or both), what it's called in the dropdown (label), and the new information (the new z in this example).
args for changes to data (where the method is either restyle or update) can also include the trace the change applies to. So if you had a bar chart and a line graph together, you may have a button that only changes the bar graph.
Using the same structure you have:
updatemenus = [go.layout.Updatemenu(
x = 1, xanchor = 'right', y = 1.15, type = "dropdown",
pad = {'t': 5, 'r': 20, 'b': 5, 'l': 30}, # around all buttons (not indiv buttons)
buttons = list([
dict(
args = [{'z': [df['GDP (BILLIONS)']]}], # original data; nest data in []
label = 'Return to the Original z',
method = 'restyle' # restyle is for trace updates
),
dict(
args = [{'z': [df['z2']]}], # nest data in []
label = 'A different z',
method = 'restyle'
),
dict(
args = [{'z': [z3]}], # nest data in []
label = 'How about this z?',
method = 'restyle'
),
dict(
args = [{'z': [z4]}], # nest data in []
label = 'Last option for z',
method = 'restyle'
)])
)]
All code used to create this graph in one chunk (includes code shown above).
import plotly.graph_objs as go
import pandas as pd
import ssl
import random
# to collect data without an error
ssl._create_default_https_context = ssl._create_unverified_context
# data used in plot
df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/2014_world_gdp_with_codes.csv')
# z values used in buttons
z2 = df['GDP (BILLIONS)'] * .667 + 12
random.seed(21)
random.shuffle(z2)
df['z2'] = z2 # example as another column in the data frame
print(df.head()) # validate as expected
z3 = df['GDP (BILLIONS)'] * .2 + 1000
random.seed(231)
random.shuffle(z3) # example as a series outside of the data frame
z4 = df['GDP (BILLIONS)']**(1/3) * df['GDP (BILLIONS)']**(1/2)
random.seed(23)
random.shuffle(z4)
z4 = z4.tolist() # example as a basic Python list
data = [go.Choropleth(
locations = df['CODE'], z = df['GDP (BILLIONS)'], text = df['COUNTRY'],
colorscale = [
[0, "rgb(5, 10, 172)"],
[0.35, "rgb(40, 60, 190)"],
[0.5, "rgb(70, 100, 245)"],
[0.6, "rgb(90, 120, 245)"],
[0.7, "rgb(106, 137, 247)"],
[1, "rgb(220, 220, 220)"]],
reversescale = True,
marker = go.choropleth.Marker(
line = go.choropleth.marker.Line(
color = 'rgb(180,180,180)', width = 0.5)),
colorbar = go.choropleth.ColorBar(
tickprefix = '$',
title = 'GDP<br>Billions US$',
len = .6) # I added this for aesthetics
)]
layout = go.Layout(
title = go.layout.Title(text = '2014 Global GDP'),
geo = go.layout.Geo(
showframe = False, showcoastlines = False,
projection = go.layout.geo.Projection(
type = 'equirectangular')
),
annotations = [go.layout.Annotation(
x = 0.55, y = 0.1, xref = 'paper', yref = 'paper',
text = 'Source: <a href="https://www.cia.gov/library/publications/the-world-factbook/fields/2195.html">\
CIA World Factbook</a>',
showarrow = False
)],
updatemenus = [go.layout.Updatemenu(
x = 1, xanchor = 'right', y = 1.15, type = "dropdown",
pad = {'t': 5, 'r': 20, 'b': 5, 'l': 30},
buttons = list([
dict(
args = [{'z': [df['GDP (BILLIONS)']]}], # original data; nest data in []
label = 'Return to the Original z',
method = 'restyle' # restyle is for trace updates only
),
dict(
args = [{'z': [df['z2']]}], # nest data in []
label = 'A different z',
method = 'restyle'
),
dict(
args = [{'z': [z3]}], # nest data in []
label = 'How about this z?',
method = 'restyle'
),
dict(
args = [{'z': [z4]}], # nest data in []
label = 'Last option for z',
method = 'restyle'
)])
)]
)
fig = go.Figure(data = data, layout = layout)
fig.show()

Resources