Plotly-Python: How to make a gapped y axis? - python

Courtesy to the original question for Plotly-R. The following will focus on Python.
Is it possible to create a plotly bar chart, e.g. any chart from the following website: plotly.com/r/bar-charts/ but with the gapped (broken) Y axis? An example from (ggplot2, I believe) attached below:

To my knowledge, plotly hasn't got any built-in functionality to do this. But it's still possible to make a figure that matches your image using subplots if you:
use make_subplots(rows=2, cols=1, vertical_spacing = <low>),
add the same traces to figure positions [1, 1] and [2, 1],
remove x-axis labels for [1, 1], and
adjust the y axes for figure positions [1, 1] and [2, 1] to respectively start and end with your desired cutoff values in a defined interval.
Plot:
Complete code:
# imports
import plotly.graph_objects as go
import plotly.express as px
import pandas as pd
from plotly.subplots import make_subplots
# data
df = pd.DataFrame({'years': [1995, 1996, 1997, 1998, 1999, 2000,
2001, 2002, 2003, 2004, 2005, 2006,
2007, 2008, 2009, 2010, 2011, 2012],
'China': [219, 146, 112, 127, 124, 180, 236,
207, 236, 263,350, 430, 474, 1526,
488, 537, 500, 439],
'Rest of world': [16, 13, 10, 11, 28, 37,
43, 55, 56, 88, 105, 156, 270,
299, 340, 403, 549, 1499]})
df.set_index('years', inplace = True)
# colors and cut-offs
colors = px.colors.qualitative.Plotly
cut_interval = [600, 1400]
# subplot setup
fig = make_subplots(rows=2, cols=1, vertical_spacing = 0.04)
fig.update_layout(title = "USA plastic scrap exports (...with some made-up values)")
# Traces for [2, 1]
# marker_color=colors[i] ensures that categories follow the same color cycle
for i, col in enumerate(df.columns):
fig.add_trace(go.Bar(x=df.index,
y=df[col],
name=col,
marker_color=colors[i],
legendgroup = col,
), row=2, col=1)
# Traces for [1, 1]
# Notice that showlegend = False.
# Since legendgroup = col the interactivity is
# taken care of in the previous for-loop.
for i, col in enumerate(df.columns):
fig.add_trace(go.Bar(x=df.index,
y=df[col],
name=col,
marker_color=colors[i],
legendgroup = col,
showlegend = False,
), row=1, col=1)
# Some aesthetical adjustments to layout
fig.update_yaxes(range=[cut_interval[1], max(df.max()*1.1)], row=1, col=1)
fig.update_xaxes(visible=False, row=1, col=1)
fig.update_yaxes(range=[0, cut_interval[0]], row=2, col=1)
fig.show()

Related

Plot A Lineplot with Y-Axis as Percentage (Using PercentFormatter)

I am using the following nested dictionary to make a lineplot:
df = {'A':
{'weight': [200, 190, 188, 180, 170],
'days_since_gym': [0, 91, 174, 205, 279],
'days_since_fasting': 40},
'B':
{'weight': [181, 175, 172, 165, 150],
'days_since_gym': [43, 171, 241, 273, 300],
'days_since_fasting': 100}}
While making the lineplot, I want the Y-Axis ticks as the percentage value, for which I'm using PercentFormatter:
# set the plot size
fig, ax = plt.subplots(2, figsize=(10, 6))
for i, x in enumerate(df.keys()):
sns.lineplot(
x=df[x]['days_since_gym'],
y=df[x]['weight'],
marker="o",
ax=ax[i],
)
ax[i].axvline(df[x]['days_since_fasting'], color='k', linestyle='--', label='Fasting Starts')
ax[i].set_xlim(left=0, right=365)
# Percentage y-axis
ax[i].yaxis.set_major_formatter(mtick.PercentFormatter())
plt.xlabel('Days Since Joined Gym')
plt.ylabel('Relastive Weight')
plt.legend(bbox_to_anchor=(1.04, 1), loc="upper left")
plt.show()
However, I don't want the default percentage value (as the fig shows). I want the 1st value would be the starting percentage and the subsequent value would be the relative percentage. For example, the 1st plot starts with 200%, which I want as 0%, and the plot ends with 170%, which I want as -something%.
Any suggestions would be appreciated. Thanks!
One way with minor changes to your code is to make the values in y relative to the first value. That is, keep everything as is and replace:
y=df[x]['weight'],
with:
y=[a-df[x]['weight'][0] for a in df[x]['weight']],

Python Plotly Radar Chart with Style

I'm trying to the image shown below and I thought python would be a good idea to do this but I'm not sure. I want to randomize lots of football players' stats, make a radar chart for each and save the charts as images.
But the plotly radar charts are not so stylish and I really want to make something stylish. How to turn the below demo code into the reference image and is it possible?
Here's a demo code:
import plotly.graph_objects as go
categories = ['Defending','Speed','Attacking',
'Technical', 'Team play']
fig = go.Figure()
fig.add_trace(go.Scatterpolar(
r=[1, 5, 2, 2, 3],
theta=categories,
fill='toself',
name='Alice'
))
fig.add_trace(go.Scatterpolar(
r=[4, 3, 2.5, 1, 2],
theta=categories,
fill='toself',
name='Bob'
))
fig.update_layout(
polar=dict(
radialaxis=dict(
visible=True,
range=[0, 5]
)),
showlegend=False
)
fig.show()
From the documentation for polar layout, it seems that Plotly does not offer much options when it comes the grid shape itself. However, Plotly allows you to create your own templates/themes or examine built-in themes.
As a starting point, you should probably analyze the plotly_dark theme as it has some features similar to your picture.
simple example with built-in template
dataset.csv
categories,player,points
Defending,alice,1
Speed,alice,5
Attacking,alice,2
Technical,alice,2
Team play,alice,3
Defending,bob,4
Speed,bob,3
Attacking,bob,2.5
Technical,bob,1
Team play,bob,2
code
import plotly.express as px
import pandas as pd
df = pd.read_csv("dataset.csv")
fig = px.line_polar(df, r="points",
theta="categories",
color="player",
line_close=True,
color_discrete_sequence=["#00eb93", "#4ed2ff"],
template="plotly_dark")
fig.update_polars(angularaxis_showgrid=False,
radialaxis_gridwidth=0,
gridshape='linear',
bgcolor="#494b5a",
radialaxis_showticklabels=False
)
fig.update_layout(paper_bgcolor="#2c2f36")
fig.show()
With the above code I don't think it is possible to modify the color of each nested shape. To be able to do so, you will probably have to create your own template and color each nested shape separately.
creating grid shape
You might have to try something similar the code below to create your desired grid shape.
import plotly.graph_objects as go
bgcolors = ["#353841", "#3f414d", "#494b5a", "#494b5a", "#58596a"]
fig = go.Figure(go.Scatterpolar(
r=[42]*8,
theta=[0, 45, 90, 135, 180, 225, 270, 315],
marker_line_width=2,
opacity=0.8,
marker=dict(color=bgcolors[0])
))
for i in range(1, 5):
fig.add_trace(go.Scatterpolar(
r=[44-6*i]*8,
theta=[0, 45, 90, 135, 180, 225, 270, 315],
marker_line_width=2,
marker=dict(color=bgcolors[i])
))
fig.update_polars(angularaxis_dtick='')
fig.update_traces(fill='toself')
fig.update_polars(angularaxis_showgrid=False,
radialaxis_showgrid=False,
radialaxis_gridwidth=0,
gridshape='linear',
radialaxis_showticklabels=False,
angularaxis_layer='above traces'
)
fig.show()
The colors are off the general shape is good.

plotly column with vertical border and color for specific column

I am looking for a solution to set a vertical border and color for a specific column(s). for this example the column "Scores".
import plotly.graph_objects as go
import plotly
fig = go.Figure(data=[go.Table(
header=dict(values=['<b>Values', '<b>Scores', 'column'],
line_color='darkslategray',
#fill_color='lightskyblue',
align='center'),
cells=dict(values=[[100, 100, 100, 300], # 1st column
[90, 90, 90, 270],
[90, 90, 90, 270]], # 2nd column
line_color='darkslategray',
#fill_color='lightcyan',
align='center'))
])
fig.update_layout(width=250, height=130)
fig.update_layout(margin=dict(l=10, r=10, t=10, b=10))
fig.show()
the perfect solution I expect looks like the table (created with excel). if somebody only know how to color the column this also would help. Thanks!
As far as I know, you cannot change the color of individual ruled lines. The only settings for lines are line width and color. The color for each cell can be specified individually by column or by an array corresponding to the cell.
import plotly.graph_objects as go
import plotly
fig = go.Figure(data=[go.Table(
header=dict(values=['<b>Values', '<b>Scores', 'column'],
line_color=['white','mediumpurple','white'],
fill_color=['white','mediumpurple','white'],
align='center'),
cells=dict(values=[[100, 100, 100, 300], # 1st column
[90, 90, 90, 270],
[90, 90, 90, 270]], # 2nd column
line_color=['white','mediumpurple','white'],
fill_color=['white','mediumpurple','white'],
align='center'))
])
fig.update_layout(width=250, height=130)
fig.update_layout(margin=dict(l=10, r=10, t=10, b=10))
fig.show()

Multi-layer Plot in plolty

Can we plot another layer of plot over a visualization using plotly through python.?
I am trying to join two points over a bubble chart.
You should be aware of the concept of traces, where we can place two types of charts in the same graph. To see the concept in action refer Multiple Chart Types in Same Graph. Just as a starting point please refer the below code snippet which does what you want.
from plotly.offline import download_plotlyjs, init_notebook_mode, plot, iplot
import plotly.graph_objs as go
from datetime import datetime
init_notebook_mode(connected=True)
trace0 = go.Scatter(
x=[1, 2, 3, 4],
y=[10, 11, 12, 13],
mode='markers',
marker=dict(
size=[40, 60, 80, 100],
)
)
trace1 = go.Scatter(
x = [1, 2, 3, 4],
y = [10, 11, 12, 13],
line = dict(
color = ('rgb(22, 96, 167)'),
width = 4,
dash = 'line')
)
data = [trace0, trace1]
iplot(data, filename='bubblechart-size')
The line that you require can also be generated using plotly shapes. Please read more about this here

Python Plotly, how to remove background horizontal line?

How to get rid of the background horizontal lines on this chart? The lines that represent the scales 5, 10, 15, etc. You can find the code below:
# Plotting waterfall chart for Years of Experience lost on DA Team
x_data = ['A', 'B', 'C', 'D', 'E']
y_data = [13, 23.5, 17.5, 10, 2.5] # y_data for positioning the annotations
text = ['27', '7', '5', '10', '5']
# Base
Base = go.Bar(x=x_data, y=[0, 20, 15, 5, 0], marker=dict(color='rgba(1,1,1, 0.0)',))
# Total
Total = go.Bar(x=x_data, y=[27, 0, 0, 0, 0], marker=dict(color='#003A6F',line=dict(color='k',width=1,)))
# Individuals
Individuals = go.Bar(x=x_data, y=[0, 7, 5, 10, 0], marker=dict( color='#FFE512',line=dict(color='k',width=1,)))
# Years of Experience Left
Years_left = go.Bar(x=x_data, y=[0, 0, 0, 0, 5], marker=dict(color='00AB39',line=dict(color='k',width=1,)))
# Put all traces in one "data" list
data = [Base, Total, Individuals, Years_left]
# Layout takes care of things like chart title, x and y axis titles and font sizes, etc.
layout = go.Layout(
title='Chart One',
barmode='stack',
yaxis=dict(title='Number of Years', titlefont=dict(size=yaxis_font_size)
, tickfont=dict(size=yaxis_font_size)),
xaxis=dict(title='Names', titlefont=dict(size=xaxis_font_size)
, tickfont=dict(size=yaxis_font_size)) ,
showlegend=False
)
annotations = []
annotations_colors = ['rgba(245, 246, 249, 1)', 'k', 'k', 'k', 'rgba(245, 246, 249, 1)'] # assign colors to annotations
for i in range(0, 5):
annotations.append(dict(x=x_data[i], y=y_data[i], text=text[i], font=dict(family='Arial', size=14, color=annotations_colors[i]), showarrow=False,))
layout['annotations'] = annotations
fig = go.Figure(data=data, layout=layout) # Standard plotly way to assign data and layout
iplot(fig, filename='Chart One')
Thanks!
Enlightening examples can be found at https://plot.ly/python/axes/
Simply add showgrid=False to your yaxis and xaxis dictionaries.
All the dict options for your xaxis can be found at https://plot.ly/python/reference/#layout-xaxis (and the yaxis is similarly at https://plot.ly/python/reference/#layout-yaxis)
we can update layout using fig.update_layout() method
by setting showgrid = False for both xaxis and yaxis parameters.
fig.update_layout(xaxis=dict(showgrid=False),
yaxis=dict(showgrid=False)
)
or
we can directly use fig.update_xaxes() and fig.update_yaxes() methods and assign showgrid=False.
fig.update_xaxes(showgrid=False)
fig.update_yaxes(showgrid=False)

Categories