Plotly: Define colours for a pie graph - (using low-level API) - python

So I got this code to make a pie chart, but I wanted to changes the colors of each class to the colors listed in the colors variable. The documentation about formatting plots in json is really hard to find so I can't figure it out. Does anyone know how to add colors to the plot? The code can be found below.
def plot_donut(df):
colors = ['#ca0020','#f4a582','#D9DDDC','#92c5de','#0571b0']
trace1 = {
"hole": 0.8,
"type": "pie",
"labels": ['-2','-1','0','1','2'],
"values": df['Time Spent (seconds)'],
"showlegend": False
}
fig = go.Figure(data=data, layout=layout)
fig.show()
plot_donut(df)

Further to my earlier comment, please see the code below for specifying named colours for a Plotly donut (pie) graph.
Like you, I much prefer to use the low-level Plotly API, rather than relying on the convenience wrappers. The code below shows how this is done at a low level.
Example code:
import plotly.io as pio
values = [2, 3, 5, 7, 11]
colours = ['#440154', '#3e4989', '#26828e', '#35b779', '#fde725']
trace1 = {'values': values,
'marker': {'colors': colours}, # <--- This is the key.
'type': 'pie',
'hole': 0.8,
'showlegend': False}
pio.show({'data': [trace1]})
Output:

Related

Combined xaxis and header of table with plotly Python

I would like to do something quite similar to the picture with plotly on python. I tried to find a way with subplots and shared_axis but no way to find a correct way. Is it possible to share the x axis of a bar chart with the column titles of a table?
graph bar with shared xaxis
this can be simulated with two traces
first trace is a standard bar chart, with yaxis domain constrained to 80% of the figure
second trace is a bar showing values as text and a fixed height against a second yaxis. yaxis2 is constrained to 10% of the domain
import plotly.express as px
import pandas as pd
import numpy as np
df = pd.DataFrame({"year": range(2011, 2022)}).assign(
pct=lambda d: np.random.uniform(-0.08, 0.08, len(d))
)
px.bar(df, x="year", y="pct").add_traces(
px.bar(df, x="year", y=np.full(len(df), 1), text="pct")
.update_traces(
yaxis="y2",
marker={"line": {"color": "black", "width": 1.5}, "color": "#E5ECF6"},
texttemplate="%{text:,.2%}",
)
.data
).update_layout(
yaxis={"domain": [0.2, 1], "tickformat": ",.2%"},
yaxis2={"domain": [0, 0.1], "visible": False},
xaxis={"title": "", "dtick": 1},
)

how to add image to plot mplfinance python

Trying to add image and price label and add more space on time and it seems like ylim= takes care of that but when i add it my whole graph disappears.
market_colors = mpf.make_marketcolors(
base_mpf_style="charles"
)
rc = {
"axes.labelcolor": "none",
"axes.spines.bottom": True,
"axes.spines.left": False,
"axes.spines.right": False,
"axes.spines.top": False,
"font.size": 10,
}
styles = mpf.make_mpf_style(
base_mpf_style="nightclouds",
marketcolors=market_colors,
gridstyle="",
rc=rc
)
filledShape = {
"y1": df['Close'].values,
"facecolor": "#2279e4"
}
(mpf.plot(df, type='line',
title='Test',
linecolor='white',
style=styles,
volume=True,
figsize=(8, 6),
figscale=0.5,
fill_between=filledShape, tight_layout=True,
scale_padding={'left': 1, 'top': 5, 'right': 1, 'bottom': 2}
))
There are three techniques that I know of to display an image on a matplotlib plot:
Axes.imshow()
Figure.figimage()
Putting the image in an AnnotationBbox
In terms of working with mplfinance, I would say that technique one, calling Axes.imshow() is probably simplest:
Step 1:
For all three of the above techniques, when you call mpf.plot() set kwarg returnfig=True:
fig axlist = mpf.plot(df,...,returnfig=True)
This will give you access to the mplfinance Figure and Axes objects.
Step 2:
Now create a new Axes object where you want the image/logo:
# Note: [left,bottom,width,height] are in terms of fraction of the Figure.
# For example [0.05,0.08,0.10,0.06] means:
# the lower/left corner of the Axes will be located:
# 5% of the way in from the left
# 8% down from the top,
# and the Axes will be
# 10% of the Figure wide and
# 6% of the Figure high.
logo_axes = fig.add_axes([left,bottom,width,height])
Step 3:
Read in the image:
import Image
im = Image.open('image_file_name.png')
Step 4:
Call imshow() on the newly created Axes, and turn of the axis lines:
logo_axes.imshow(im)
logo_axes.axis('off')
Step 5:
Since returnfig=True causes mplfinance to not show the Figure, call mpf.show()
mpf.show()
I'm not sure if this answer will help you or not since I'm not sure what kind of images you want to add. I assume you want to add a corporate logo or something like that, so I did some research and found an answer to whether you can add a watermark to an mpf. I used this answer as a guide and added the icons used on stackoveflow.com to the graph. However, it was not possible to add them to the axes, so I had to add them to the fig. I have changed the style to add the image.
img = plt.imread('./data/se-icon.png')
market_colors = mpf.make_marketcolors(
base_mpf_style="charles"
)
rc = {
"axes.labelcolor": "none",
"axes.spines.bottom": True,
"axes.spines.left": False,
"axes.spines.right": False,
"axes.spines.top": False,
"font.size": 10,
}
styles = mpf.make_mpf_style(
base_mpf_style="yahoo",# nightclouds
marketcolors=market_colors,
gridstyle="",
rc=rc
)
filledShape = {
"y1": df['Close'].values,
"facecolor": "#2279e4"
}
fig, axes = mpf.plot(df, type='line',
title='Test',
linecolor='white',
style=styles,
volume=True,
figsize=(8, 6),
figscale=0.5,
fill_between=filledShape,
tight_layout=True,
scale_padding={'left': 1, 'top': 5, 'right': 1, 'bottom': 2},
returnfig=True
)
#axes[0].imshow(img)
#height = img.shape[1]
fig.figimage(img, 0, fig.bbox.ymax - height*1.5)
plt.show()

Modify values and path in plotly express sunburst using updatemenus

I'm plotting datasets with plotly express as sunburst charts.
One thing I'm trying to achieve is the possibility to select the values to be plotted so that the plot gets updated if the values change meaning that a different column in the dataframe is selected.
I've created an example based on this sunburst example in the official docs
https://plotly.com/python/sunburst-charts/#sunburst-of-a-rectangular-dataframe-with-plotlyexpress
There the column 'total_bill' is selected for plotting and that works. I can recreate the plot in that example.
Now I would like to use updatemenus to switch that to the 'tip' column that also holds floats and should be usable.
The example code I've tried:
import plotly.express as px
df = px.data.tips()
updatemenus = [{'buttons': [{'method': 'update',
'label': 'total_bill',
'args': [{'values': 'total_bill'}]
},
{'method': 'update',
'label': 'tip',
'args': [{'values': 'tip'}]
}],
'direction': 'down',
'showactive': True,}]
fig = px.sunburst(df, path=['day', 'time', 'sex'], values='total_bill')
fig.update_layout(updatemenus=updatemenus)
fig.show()
Now this will successfully plot the same plot as in the example, but when I select back and forth between the two updatemenu options, it doesn't behave properly.
I've also tried to use Series everywhere, but the results is the same.
I've also looked at this example, which has a similar focus
Plotly: How to select graph source using dropdown?
but the answers there didn't solve my problem either, since the sunburst in some way seems to behave differently from the scatter plot?
Any idea how to get this working?
similar to solution you arrived at. Use Plotly Express to build all the figures, collect into a dict
menu can now be built with dict comprehension
import plotly.express as px
df = px.data.tips()
# construct figures for all columns that can provide values
figs = {
c: px.sunburst(df, path=["day", "time", "sex"], values=c)
for c in ["total_bill", "tip"]
}
# choose a column that becomes the figure
fig = figs["total_bill"]
# now build menus, that use parameters that have been pre-built using plotly express
fig.update_layout(
updatemenus=[
{
"buttons": [
{
"label": c,
"method": "restyle",
"args": [
{
"values": [figs[c].data[0].values],
"hovertemplate": figs[c].data[0].hovertemplate,
}
],
}
for c in figs.keys()
]
}
]
)
Ok, I found one solution that works, but maybe someone could point me towards a "cleaner" solution, if possible.
I stumbled across this question that is actually unrelated:
Plotly: How to create sunburst subplot using graph_objects?
There, one solution was to save the figure data of a plotly express figure and reuse it in a graph objects figure.
This gave me an idea, that I could maybe save the data of each figure and then reuse (and update/modify) it in a third figure.
And, as it turns out, this works!
So here is the working example:
import plotly.express as px
df = px.data.tips()
# create two figures based on the same data, but with different values
fig1 = px.sunburst(df, path=['day', 'time', 'sex'], values='total_bill')
fig2 = px.sunburst(df, path=['day', 'time', 'sex'], values='tip')
# save the data of each figure so we can reuse that later on
ids1 = fig1['data'][0]['ids']
labels1 = fig1['data'][0]['labels']
parents1 = fig1['data'][0]['parents']
values1 = fig1['data'][0]['values']
ids2 = fig2['data'][0]['ids']
labels2 = fig2['data'][0]['labels']
parents2 = fig2['data'][0]['parents']
values2 = fig2['data'][0]['values']
# create updatemenu dict that changes the figure contents
updatemenus = [{'buttons': [{'method': 'update',
'label': 'total_bill',
'args': [{
'names': [labels1],
'parents': [parents1],
'ids': [ids1],
'values': [values1]
}]
},
{'method': 'update',
'label': 'tip',
'args': [{
'names': [labels2],
'parents': [parents2],
'ids': [ids2],
'values': [values2]
}]
}],
'direction': 'down',
'showactive': True}]
# create the actual figure to be shown and modified
fig = px.sunburst(values=values1, parents=parents1, ids=ids1, names=labels1, branchvalues='total')
fig.update_layout(updatemenus=updatemenus)
fig.show()

Plotly: Choose a different intersection of X and Y axes

In Plotly, in order to create scatter plots, I usually do the following:
fig = px.scatter(df, x=x, y=y)
fig.update_xaxes(range=[2, 10])
fig.update_yaxes(range=[2, 10])
I want the yaxis to intersect the xaxis at x=6. So, instead of left yaxis representing negative numbers, I want it to be from [2,6] After the intersection, right side of graph is from [6,10].
Likewise, yaxis from below axis goes from [2,6]. Above the xaxis, it goes from [6,10].
How can I do this in Plotly?
Following on from my comment, as far as I am aware, what you're after is not currently available.
However, here is an example of a work-around which uses a shapes dictionary to add horizontal and vertical lines - acting as intersecting axes - placed at your required x/y intersection of 6.
Sample dataset:
import numpy as np
x = (np.random.randn(100)*2)+6
y1 = (np.random.randn(100)*2)+6
y2 = (np.random.randn(100)*2)+6
Example plotting code:
import plotly.io as pio
layout = {'title': 'Intersection of X/Y Axes Demonstration'}
shapes = []
traces = []
traces.append({'x': x, 'y': y1, 'mode': 'markers'})
traces.append({'x': x, 'y': y2, 'mode': 'markers'})
shapes.append({'type': 'line',
'x0': 2, 'x1': 10,
'y0': 6, 'y1': 6})
shapes.append({'type': 'line',
'x0': 6, 'x1': 6,
'y0': 2, 'y1': 10})
layout['shapes'] = shapes
layout['xaxis'] = {'range': [2, 10]}
layout['yaxis'] = {'range': [2, 10]}
pio.show({'data': data, 'layout': layout})
Output:
Comments (TL;DR):
The example code shown here uses the low-level Plotly API (plotly.io), rather than a convenience wrapper such as graph_objects or express. The reason is that I (personally) feel it's helpful to users to show what is occurring 'under the hood', rather than masking the underlying code logic with a convenience wrapper.
This way, when the user needs to modify a finer detail of the graph, they will have a better understanding of the lists and dicts which Plotly is constructing for the underlying graphing engine (orca).
I think fig.add_hline() and fig.add_vline() is the function your need.
Example code
import plotly.express as px
import pandas as pd
df = pd.DataFrame({'x':[6,7,3], 'y':[4,5,6]})
fig = px.scatter(df, x='x', y='y')
fig.update_xaxes(range=[2, 10])
fig.update_yaxes(range=[2, 10])
fig.add_hline(y=4)
fig.add_vline(x=6)
fig.show()
Output

How can I add a single line to a scatter plot in plotly?

Consider the following MWE to draw a scatter plot using the python API to plotly:
import plotly.plotly as py
import plotly.graph_objs
import plotly.offline
plotly.offline.init_notebook_mode()
data = list(range(10))
trace = plotly.graph_objs.Scatter(
x=list(range(len(data))),
y=data
)
plotly.offline.iplot([trace])
What if I now want to add a (say) horizontal line to this plot?
I went through the documentation, for example the section on line and scatter and that on line charts, but none of the examples seem to cover how to overlay different plots, or simply draw straight lines and similar shapes.
A naive approach to do this is to just add the line as a second scatter plot, like the following:
import plotly.plotly as py
import plotly.graph_objs
import plotly.offline
plotly.offline.init_notebook_mode()
data = list(range(10))
trace = plotly.graph_objs.Scatter(
x=list(range(len(data))),
y=data
)
trace_line = plotly.graph_objs.Scatter(
x=list(range(len(data))),
y=[4] * len(data),
mode='lines'
)
plotly.offline.iplot([trace, trace_line])
This approach seems however to be suboptimal: aside for the verbosity required to add a single line, it also makes me manually "sample" the straight line, and it adds the line height to the tooltip on mouse hover.
Is there a better approach to achieve this?
Hi from your question I can see that you need plotly shapes functionality and generate a horizontal line for the plot.
Please find below the code for doing the same graph you have shown in the question
Code:
from plotly.offline import iplot
import plotly.graph_objs as go
data = list(range(10))
trace = go.Scatter(
x=list(range(len(data))),
y=data
)
layout = {
'shapes': [
# Line Horizontal
{
'type': 'line',
'x0': 0,
'y0': 4,
'x1': 10,
'y1': 4,
'line': {
'color': 'rgb(50, 171, 96)',
'width': 4
},
}
],
'showlegend': True
}
fig = {
'data': [trace],
'layout': layout,
}
iplot(fig)
Output:
Additional reference:
plotly shapes examples
plotly shapes reference
Alternatively, you could use the add_shape method, see the doc here. If you add the following code, you could add the line same as y=4 as above.
fig.add_shape(type="line",
x0=4,
y0=0,
x1=4,
y1=10)
You can just add the next line:
fig.add_hline(y=4, line_width=2, line_dash='dash')
Also checkout the documentation for further deep into the features that plotly recently has added.

Categories

Resources