Remove zero from ternary plot - python

I have the following plot and I want to remove the 0 in the origins.
import plotly.graph_objects as go
import plotly.express as px
fig = go.Figure(go.Scatterternary({
'mode': 'markers', 'a': [0.3],'b': [0.5], 'c': [0.6],
'marker': {'color': 'AliceBlue','size': 14,'line': {'width': 2} },
}))
fig.update_layout({
'ternary': {
'sum': 100,
'aaxis': {'nticks':1, 'ticks':""},
'baxis': {'nticks':1},
'caxis': {'nticks':1} }})
fig.update_traces( hovertemplate = "<b>CatA: %{a:.0f}<br>CatB: %{b:.0f}<br>CatC: %{c:.0f}<extra></extra>")
fig.show()
I am surprised because documentation here says the minimum of nticks is 1, not 0 (which does not work). How can I remove the 0 from the corners?

as u mentioned doc says ntick specifies the maximum number of ticks for the particular axis.
So its true, cannot be zero.
fig.update_ternaries(aaxis_showticklabels=False)
fig.update_ternaries(baxis_showticklabels=False)
fig.update_ternaries(caxis_showticklabels=False)

Related

Plotly make marker overlay add_trace

I have the following Scatterternary plot below. Whenever I add_trace, the marker remains under it (so you cannot even hover it). How can I make the marker circle above the red area? [In implementation, I will have several areas and the marker may move around]
I tried adding fig.update_ternaries(aaxis_layer="above traces",baxis_layer="above traces", caxis_layer="above traces") as shown in the documentation without success. There is also another explanation for the boxplots with the same issue but I don't know how to implement it in this case.
import plotly.graph_objects as go
fig = go.Figure(go.Scatterternary({
'mode': 'markers', 'a': [0.3],'b': [0.5], 'c': [0.6],
'marker': {'color': 'AliceBlue','size': 14,'line': {'width': 2} },}))
fig.update_layout({
'ternary': {
'sum': 100,
'aaxis': {'nticks':1, 'ticks':""},
'baxis': {'nticks':1},
'caxis': {'nticks':1} }})
fig.add_trace(go.Scatterternary(name='RedArea',a=[0.1,0.1,0.6],b=[0.7,0.4,0.5],c=[0.2,0.6,0.8],mode='lines',opacity=0.35,fill='toself',
fillcolor='red'))
fig.update_traces( hovertemplate = "<b>CatA: %{a:.0f}<br>CatB: %{b:.0f}<br>CatC: %{c:.0f}<extra></extra>")
fig.show()
In this case, the markers can be displayed by swapping the drawing order. plotly does not provide the ability to control the drawing order, so changing the order of the code is the solution. However, it is not clear if this technique is possible for all graphs.
import plotly.graph_objects as go
fig = go.Figure()
fig.update_layout({
'ternary': {
'sum': 100,
'aaxis': {'nticks':1, 'ticks':""},
'baxis': {'nticks':1},
'caxis': {'nticks':1} }})
fig.add_trace(go.Scatterternary(
name='RedArea',
a=[0.1,0.1,0.6],
b=[0.7,0.4,0.5],
c=[0.2,0.6,0.8],
mode='lines',
opacity=0.35,
fill='toself',
fillcolor='red')
)
fig.add_trace(go.Scatterternary({
'mode': 'markers', 'a': [0.3],'b': [0.5], 'c': [0.6],
'marker': {'color': 'AliceBlue','size': 14,'line': {'width': 2} },}))
fig.update_traces( hovertemplate = "<b>CatA: %{a:.0f}<br>CatB: %{b:.0f}<br>CatC: %{c:.0f}<extra></extra>")
fig.show()

Plotly: How to inspect and make changes to a plotly figure?

Related questions have already been asked and before e.g.
How can I search for the options for a particular property of a plotly figure?
Plotly: How to inspect the basic figure structure (version 4)
But the answers to these questions have been limited by the fact that not all parameters have been available through Python, meaning that the real answers were buried somewhere in JavaScript. But for newer versions of plotly, how can you inspect and edit a plotly figure? How could you, for example, find out what the background color of a figure is? And then change it? From the second link above you can see that fig.show and print(fig) will reveal some details about the figure structure. But certainly not all of it. The code snippet below will produce the following plot:
Plot:
Code:
import plotly.graph_objects as go
import plotly.express as px
df = px.data.gapminder().query("country=='Canada'")
fig = px.line(df, x="year", y="lifeExp", title='Life expectancy in Canada')
fig.show()
Running fig.show will now partly reveal the structure of the figure in the form of a dict:
<bound method BaseFigure.show of Figure({
'data': [{'hovertemplate': 'year=%{x}<br>lifeExp=%{y}<extra></extra>',
'legendgroup': '',
'line': {'color': '#636efa', 'dash': 'solid'},
'mode': 'lines',
'name': '',
'orientation': 'v',
'showlegend': False,
'type': 'scatter',
'x': array([1952, 1957, 1962, 1967, 1972, 1977, 1982, 1987, 1992, 1997, 2002, 2007],
dtype=int64),
'xaxis': 'x',
'y': array([68.75 , 69.96 , 71.3 , 72.13 , 72.88 , 74.21 , 75.76 , 76.86 , 77.95 ,
78.61 , 79.77 , 80.653]),
'yaxis': 'y'}],
'layout': {'legend': {'tracegroupgap': 0},
'template': '...',
'title': {'text': 'Life expectancy in Canada'},
'xaxis': {'anchor': 'y', 'domain': [0.0, 1.0], 'title': {'text': 'year'}},
'yaxis': {'anchor': 'x', 'domain': [0.0, 1.0], 'title': {'text': 'lifeExp'}}}
})
But as you can see for yourself, there are a lot of details missing. So how can you peform a more complete figure introspection?
As of version 4.10, the plotly developers have introduced the awesome fig.full_figure_for_development() function which they talk about here. There you'll see that:
fig.full_figure_for_development() function will return a new go.Figure
object, prepopulated with the same values you provided, as well as all
the default values computed by Plotly.js, to allow you to learn more
about what attributes control every detail of your figure and how you
can customize them. This function is named “for development” because
it’s not necessary to use it to produce figures, but it can be really
handy to explore figures while you’re figuring out how to build them.
So building on the example in the question, the following snippet will produce an output of about 180 lines containing, among a plethora of other details, this part about the figure layout:
'margin': {'autoexpand': True, 'b': 80, 'l': 80, 'pad': 0, 'r': 80, 't': 100},
'modebar': {'activecolor': 'rgba(68, 68, 68, 0.7)',
'bgcolor': 'rgba(255, 255, 255, 0.5)',
'color': 'rgba(68, 68, 68, 0.3)',
'orientation': 'h'},
'newshape': {'drawdirection': 'diagonal',
'fillcolor': 'rgba(0,0,0,0)',
'fillrule': 'evenodd',
'layer': 'above',
'line': {'color': '#444', 'dash': 'solid', 'width': 4},
'opacity': 1},
'paper_bgcolor': 'white',
'plot_bgcolor': '#E5ECF6',
'separators': '.,',
'showlegend': False,
'spikedistance': 20,
And there you can also see the background color of the plot as 'plot_bgcolor': '#E5ECF6'. And you probably know that you can set the background color using to for example 'grey' using fig.update_layout(plot_bgcolor='grey'). But now you know how to get it as well:
# In:
fig.layout.plot_bgcolor
# Out:
'#E5ECF6'
And in knowing how to do this, you know how to get and set almost any attribute of a plotly figure. And it doesn't matter if you've built the figure using plotly.graph_objects or plotly.express

how to set colorscale with reference to dates in plotly python

first question so go easy on me please!
I'm trying to create a scatter plot in plotly where the points are coloured according to a datetime column, but it seems to error out. it works fine if I set the color to, say, a numeric column. is there a way to do this please?
Sample code below. if I change color to, say np.arange(0,graph_data.shape[0]) it would work fine but the colorbar labels would be meaningless.
fig1 = go.Figure()
fig1.add_trace(go.Scatter(
x=graph_data['x_data'],
y=graph_data['y_data'],
mode='markers',
marker={
'size': 15,
'opacity': 0.95,
'line': {'width': 0.5, 'color': 'white'},
'color': graph_data['date'],
'colorbar': {'title': 'Date'},
'colorscale': 'Viridis'
}
)
There may be a better way to do this, but one possible workaround is to convert your datetime to seconds after a given date. You could try the following using the datetime module:
int(datetime.datetime.utcnow().timestamp())
This will then be an integer which will be understood by the scatter function.
Using the principles of Matt's work around, I created a 'number of days from start' column for the colorscale to reference and then customised tick labels and spacing on the colour bar as follows:
# 'date' column contains the dates I want to set colorscale on
# set minimum date
min_date = graph_data['date'].min()
# create column giving number of days from the minimum date, as the colour reference
graph_data['days'] = graph_data['date'].apply(lambda x: (x-min_date).days)
# here I want colorbar tick labels every 7 days, so I create a list of the
# required multiples of 7
max_days = graph_data['days'].max()
fig1ticks = np.arange(0, (int(max_days/7)+1)*7, 7)
# use datetime.timedelta function to create the dates that match the tick values
fig1datetimes = [min_date + datetime.timedelta(days=i) for i in fig1ticks.tolist()]
# and create text strings of these dates in a suitable format
fig1text = [i.strftime("%d-%b-%Y") for i in fig1datetimes]
fig1 = go.Figure()
fig1.add_trace(go.Scatter(
x=graph_data['x_data'],
y=graph_data['y_data'],
mode='markers',
marker={
'size': 15,
'opacity': 0.95,
'line': {'width': 0.5, 'color': 'white'},
# set color reference to new 'days' column
'color': graph_data['days'],
# set 'tickvals' and 'ticktext' in colorbar dict
'colorbar': {'title': 'Date',
'tickvals': fig1ticks,
'ticktext': fig1text,
},
'colorscale': 'Viridis'
}
)
)

Plotly: How to inspect the basic figure structure (version 4)

For older versions of plotly, for example in Jupyterlab, you could simply run figure to inspect the basics of your figure like this:
Ouput:
{'data': [{'marker': {'color': 'red', 'size': '10', 'symbol': 104},
'mode': 'markers+lines',
'name': '1st Trace',
'text': ['one', 'two', 'three'],
'type': 'scatter',
'x': [1, 2, 3],
'y': [4, 5, 6]}],
'layout': {'title': 'First Plot',
'xaxis': {'title': 'x1'},
'yaxis': {'title': 'x2'}}}
Code for versions prior to V4:
import plotly.plotly as py
import plotly.graph_objs as go
trace1 = go.Scatter(x=[1,2,3], y=[4,5,6], marker={'color': 'red', 'symbol': 104, 'size': "10"},
mode="markers+lines", text=["one","two","three"], name='1st Trace')
data=go.Data([trace1])
layout=go.Layout(title="First Plot", xaxis={'title':'x1'}, yaxis={'title':'x2'})
figure=go.Figure(data=data,layout=layout)
#py.iplot(figure, filename='pyguide_1')
figure
If you do the same thing now with a similar setup, the same approach will not produce the figure basics, but rather plot the figure itself:
Code:
import pandas as pd
import plotly.graph_objects as go
trace1 = go.Scatter(x=[1,2,3], y=[4,5,6], marker={'color': 'red', 'symbol': 104},
mode="markers+lines", text=["one","two","three"], name='1st Trace')
figure = go.Figure(data=trace1)
figure
Output:
In many ways this is similar to how you for example would build and plot a figure with ggplot in R. And since plotly is available for both R and Python I thinks this makes sense after all. But I'd really like to know how to access that basic setup.
What I've tried:
I think this change is due to the fact that figure is now a plotly.graph_objs._figure.Figure and used to be a dictionary(?). So figure['data'] and figure['layout'] are still dicts with necessary and interesting content:
Output from figure['data']
(Scatter({
'marker': {'color': 'red', 'symbol': 104},
'mode': 'markers+lines',
'name': '1st Trace',
'text': [one, two, three],
'x': [1, 2, 3],
'y': [4, 5, 6]
}),)
Output from figure['layout']
Layout({
'template': '...'
})
And of course options such as help(figure) and dir(figure) are helpful, but produces a very different output.
I just found out that 'forgetting' the brackets for figure.show() will give me exactly what I'm looking for. So with a setup similar to the code in the question and with plotly V4, simply running figure.show will give you this:
Output:
<bound method BaseFigure.show of Figure({
'data': [{'marker': {'color': 'red', 'symbol': 104},
'mode': 'markers+lines',
'name': '1st Trace',
'text': [one, two, three],
'type': 'scatter',
'x': [1, 2, 3],
'y': [4, 5, 6]}],
'layout': {'template': '...'}
})>
Code:
import pandas as pd
import plotly.graph_objects as go
trace1 = go.Scatter(x=[1,2,3], y=[4,5,6], marker={'color': 'red', 'symbol': 104},
mode="markers+lines", text=["one","two","three"], name='1st Trace')
figure = go.Figure(data=trace1)
figure.show

Plotly: How to select graph source using dropdown?

I'm trying to embed multiple, selectable graphs in a single figure using Plotly, using a dropdown figure. I followed the dropdown example from Plotly, but they only show how to change graph characteristics (like visible, or type), not the underlying data. In my situation, I have a static X-axis and want to change the Y-values. Here's a minimal working example that can be run in a jupyter notebook:
import plotly
from plotly import graph_objs as go, offline as po, tools
po.init_notebook_mode()
import numpy as np
import json
x = list(np.linspace(-np.pi, np.pi, 100))
values_1 = list(np.sin(x))
values_2 = list(np.tan(x))
line = go.Scatter(
x=x,
y=values_1
)
updatemenus = [
{
'buttons': [
{
'method': 'restyle',
'label': 'Val 1',
'args': [
{'y': json.dumps(values_1)},
]
},
{
'method': 'restyle',
'label': 'Val 2',
'args': [
{'y': json.dumps(values_2)},
]
}
],
'direction': 'down',
'showactive': True,
}
]
layout = go.Layout(
updatemenus=updatemenus,
)
figure = go.Figure(data=[line], layout=layout)
po.iplot(figure)
However, while the approach seems to work like advertised for general graph attributes (like 'visible'), when I use 'y', it produces a straight line, where y goes from 0 to len(y), instead of the actual data I gave it. Here are images of the initial render, and then what happens when I select the dropdown item for the Tan(X) graph, then go back to the Sin(X):
How do I embed the data for multiple graphs into a single figure so that the user can select which one they want to view?
Updated answer using graph_objects:
As of version 4, you don't have to worry about offline versus online functionality. So drop the from plotly import graph_objs as go, offline as po and po.init_notebook_mode(), and just use import plotly.graph_objects as go. I've updated my original answer with a complete code snippet that shows the whole approach with multiple traces using plotly.graph_objects at the end. The solution to the question as it still stands will still be the same, namely:
'y' in updatemenus does not take a single list as an argument, but rather a list of lists like in 'y' = [values_1] where values_1 is a list in itself. So just replace your lines
{'y': json.dumps(values_1)}, and {'y': json.dumps(values_2)},
with
{'y': [values_1]}, and {'y': [values_2]},
to get these plots for the different options Val 1 and Val 2:
Some Details:
Values_1 is, unsurprisingly, a list of length 100 where each element is of type numpy.float. Replacing json.dumps(values_1) with values_1, and json.dumps(values_2) with values_2 will render the same plots as in your question. The reason why these plots are just straight lines, seems to be that it's the length of your lists that are being plotted, and not the values contained in that list. Or something to that effect.
Setting 'y' = values_1 is the same thing as assigning a single list to 'y'. But 'y' in updatemenus does not take a single list as an argument, but rather a list of lists like in 'y' = [values_1]. Why? Because you might want to plot multiple lists in the same figure like 'y' = [values_1, values_1b]. Have a look:
Plot for dropdown option Var 1:
Plot for dropdown option Var 2
Complete original code:
import plotly
from plotly import graph_objs as go, offline as po, tools
po.init_notebook_mode()
import numpy as np
import json
x = list(np.linspace(-np.pi, np.pi, 100))
values_1 = list(np.sin(x))
values_1b = [elem*-1 for elem in values_1]
values_2 = list(np.tan(x))
values_2b = [elem*-1 for elem in values_2]
line = go.Scatter(
x=x,
y=values_1
)
line2 = go.Scatter(
x=x,
y=values_1b
)
updatemenus = [
{
'buttons': [
{
'method': 'restyle',
'label': 'Val 1',
'args': [
{'y': [values_1, values_1b]},
]
},
{
'method': 'restyle',
'label': 'Val 2',
'args': [
{'y': [values_2, values_2b]},
]
}
],
'direction': 'down',
'showactive': True,
}
]
layout = go.Layout(
updatemenus=updatemenus,
)
figure = go.Figure(data=[line, line2], layout=layout)
po.iplot(figure)
Complete updated code:
# imports
import plotly.graph_objects as go
import numpy as np
# data
x = list(np.linspace(-np.pi, np.pi, 100))
values_1 = list(np.sin(x))
values_1b = [elem*-1 for elem in values_1]
values_2 = list(np.tan(x))
values_2b = [elem*-1 for elem in values_2]
# plotly setup]
fig = go.Figure()
# Add one ore more traces
fig.add_traces(go.Scatter(x=x, y=values_1))
fig.add_traces(go.Scatter(x=x, y=values_1b))
# construct menus
updatemenus = [{'buttons': [{'method': 'update',
'label': 'Val 1',
'args': [{'y': [values_1, values_1b]},]
},
{'method': 'update',
'label': 'Val 2',
'args': [{'y': [values_2, values_2b]},]}],
'direction': 'down',
'showactive': True,}]
# update layout with buttons, and show the figure
fig.update_layout(updatemenus=updatemenus)
fig.show()
Plot with version 4 default layout:

Categories

Resources