Is it possible to reverse bullet charts in plotly? - python

I created a bullet chart with a negative and positive dimension in plotly.go. However, when plotting my bar it always starts from -1. Is there a way to set the starting point at zero, so it can align in both dimensions from there?
Reproducable example:
act = 0.123
avg = 0.13
before = 0.15
fig = go.Figure(go.Indicator(
mode="number+gauge+delta", value=act,
domain={'x': [0.1, 1], 'y': [0, 1]},
title={'text': "<b>S-Score</b>"},
delta={'reference': before},
gauge={
'shape': "bullet",
'tick0':0,
'axis': {'range': [-1, 1]},
'threshold': {
'line': {'color': "white", 'width': 2},
'thickness': 0.75, 'value': avg},
'steps': [
{'range': [-1, 0], 'color': "#ff6666"},
{'range': [0, 1], 'color': "#89ac76"}
],
'bar': {'color': "grey"}}))
Actual Output:
Output I want:

I've done a lot of research and haven't found a solution. I propose a trick approach and a proposal to change the x-axis. This is a bit far from the answer you expect.
import plotly.graph_objects as go
act = 0.123
avg = 0.13
before = 0.15
fig = go.Figure(go.Indicator(
mode = "number+gauge+delta", value = act,
domain = {'x': [0.1, 1], 'y': [0, 1]},
title = {'text' :"<b>S-Score</b>"},
delta = {'reference': before},
gauge = {
'shape': "bullet",
'axis': {'range': [-1, 1]},
'threshold': {
'line': {'color': "white", 'width': 2},
'thickness': 0.75,
'value': avg},
'steps': [
{'range': [-1, 0], 'color': "#ff6666"},
{'range': [0, 1], 'color': "#89ac76"}],
'bar': {'color':'#ff6666'}
}))
fig.update_layout(height = 250)
fig.show()
import plotly.graph_objects as go
act = 0.123
avg = 0.13
before = 0.15
fig = go.Figure(go.Indicator(
mode = "number+gauge+delta", value = act,
domain = {'x': [0.1, 1], 'y': [0, 1]},
title = {'text' :"<b>S-Score</b>"},
delta = {'reference': before},
gauge = {
'shape': "bullet",
'axis': {'range': [0, 1]},
'threshold': {
'line': {'color': "white", 'width': 2},
'thickness': 0.75,
'value': avg},
'steps': [
{'range': [-1, 0], 'color': "#ff6666"},
{'range': [0, 1], 'color': "#89ac76"}],
'bar': {'color':'grey',
'line': {'color':'#444', 'width':2},
}}))
fig.update_layout(height = 250)
fig.show()

Related

Cannot create secondary x-axis with xlsxwriter

I am trying to generate a chart with a secondary x-axis, but I can't get the secondary x-axis to be added to the chart.
Below is the code I'm using. If I change "x2_axis" to "y2_axis" and "set_x2_axis" to "set_y2_axis", then I am able to create a secondary y axis successfully -- but it does not work for a secondary x axis. Am I doing something wrong?
import xlsxwriter
workbook = xlsxwriter.Workbook('test.xlsx')
worksheet = workbook.add_worksheet()
data = [
[1, 2, 3, 4, 5],
[10, 40, 50, 20, 10],
[1,1,2,2,3,3,4,4,5,5],
[200,200,100,100,300,300,250,250,350,350]
]
worksheet.write_column('A2', data[0])
worksheet.write_column('B2', data[1])
worksheet.write_column('C2', data[2])
worksheet.write_column('D2', data[3])
chart= workbook.add_chart({'type': 'line'})
chart.add_series ({
'name': 'Primary',
'categories': '=Sheet1!$A$2:$A$6',
'values': '=Sheet1!$B$2:$B$6',
})
chart.add_series ({
'name': 'Secondary',
'categories': '=Sheet1!$C$2:$C$11',
'values': '=Sheet1!$D$2:$D$11',
'x2_axis': True
})
chart.set_x_axis({
'name': 'Primary Axis',
'interval_unit': 1,
'interval_tick': 1,
'major_tick_mark': 'none',
})
chart.set_y_axis({
'name': 'Value',
})
chart.set_x2_axis({
'label_position': 'low',
'name': 'Secondary Axis',
'visible': True
})
worksheet.insert_chart('B20', chart)
workbook.close()
Setting a secondary X axis in Excel (or XlsxWriter) isn't obvious, in comparison to setting a secondary Y axis. Generally, you need to add a secondary Y and X axis pair before you can set a secondary X axis. Something like this:
import xlsxwriter
workbook = xlsxwriter.Workbook('test.xlsx')
worksheet = workbook.add_worksheet()
data = [
[1, 2, 3, 4, 5],
[10, 40, 50, 20, 10],
[1, 1, 2, 2, 3, 3, 4, 4, 5, 5],
[200, 200, 100, 100, 300, 300, 250, 250, 350, 350]
]
worksheet.write_column('A2', data[0])
worksheet.write_column('B2', data[1])
worksheet.write_column('C2', data[2])
worksheet.write_column('D2', data[3])
chart = workbook.add_chart({'type': 'line'})
chart.add_series({
'name': 'Primary',
'categories': '=Sheet1!$A$2:$A$6',
'values': '=Sheet1!$B$2:$B$6',
})
chart.add_series({
'name': 'Secondary',
'categories': '=Sheet1!$C$2:$C$11',
'values': '=Sheet1!$D$2:$D$11',
'x2_axis': True,
'y2_axis': True,
})
chart.set_x_axis({
'name': 'Primary Axis',
'interval_unit': 1,
'interval_tick': 1,
'major_tick_mark': 'none',
})
chart.set_y_axis({
'name': 'Y Values 1',
})
chart.set_y2_axis({
'name': 'Y Values 2',
'crossing': 'max',
})
chart.set_x2_axis({
'label_position': 'high',
'name': 'Secondary Axis',
'visible': True,
})
worksheet.insert_chart('B20', chart)
workbook.close()
Output:

Plotly: How to show subplot titles at the bottom

Given this example from plotly documentation
from plotly.subplots import make_subplots
import plotly.graph_objects as go
fig = make_subplots(
rows=2, cols=2,
specs=[[{}, {}],
[{"colspan": 2}, None]],
subplot_titles=("First Subplot","Second Subplot", "Third Subplot"))
fig.add_trace(go.Scatter(x=[1, 2], y=[1, 2]),
row=1, col=1)
fig.add_trace(go.Scatter(x=[1, 2], y=[1, 2]),
row=1, col=2)
fig.add_trace(go.Scatter(x=[1, 2, 3], y=[2, 1, 2]),
row=2, col=1)
fig.update_layout(showlegend=False, title_text="Specs with Subplot Title")
fig.show()
Which is displayed as
How to change it so the subtitle is shown at the bottom?
As far as I know, there is no direct setting, so you can check the actual annotation position in fig.layout and adjust it.
from plotly.subplots import make_subplots
import plotly.graph_objects as go
fig = make_subplots(
rows=2, cols=2,
specs=[[{}, {}],
[{"colspan": 2}, None]],
subplot_titles=("First Subplot","Second Subplot", "Third Subplot"))
fig.add_trace(go.Scatter(x=[1, 2], y=[1, 2]),
row=1, col=1)
fig.add_trace(go.Scatter(x=[1, 2], y=[1, 2]),
row=1, col=2)
fig.add_trace(go.Scatter(x=[1, 2, 3], y=[2, 1, 2]),
row=2, col=1)
fig.update_layout(showlegend=False, title_text="Specs with Subplot Title")
fig.layout.annotations[0].update(y=0.40)
fig.layout.annotations[1].update(y=0.40)
fig.layout.annotations[2].update(y=-0.2)
fig.show()
fig.layout
Layout({
'annotations': [{'font': {'size': 16},
'showarrow': False,
'text': 'First Subplot',
'x': 0.225,
'xanchor': 'center',
'xref': 'paper',
'y': 1.0,
'yanchor': 'bottom',
'yref': 'paper'},
{'font': {'size': 16},
'showarrow': False,
'text': 'Second Subplot',
'x': 0.775,
'xanchor': 'center',
'xref': 'paper',
'y': 1.0,
'yanchor': 'bottom',
'yref': 'paper'},
{'font': {'size': 16},
'showarrow': False,
'text': 'Third Subplot',
'x': 0.5,
'xanchor': 'center',
'xref': 'paper',
'y': 0.375,
'yanchor': 'bottom',
'yref': 'paper'}],
'showlegend': False,
'template': '...',
'title': {'text': 'Specs with Subplot Title'},
'xaxis': {'anchor': 'y', 'domain': [0.0, 0.45]},
'xaxis2': {'anchor': 'y2', 'domain': [0.55, 1.0]},
'xaxis3': {'anchor': 'y3', 'domain': [0.0, 1.0]},
'yaxis': {'anchor': 'x', 'domain': [0.625, 1.0]},
'yaxis2': {'anchor': 'x2', 'domain': [0.625, 1.0]},
'yaxis3': {'anchor': 'x3', 'domain': [0.0, 0.375]}
})

Plotly vertical line with legend in python

In plotly website, there is example that can use shape function add vertical or horizontal line in plotly.
import plotly.plotly as py
import plotly.graph_objs as go
trace0 = go.Scatter(
x=[2, 3.5, 6],
y=[1, 1.5, 1],
mode='text',
)
data = [trace0]
layout = {
'xaxis': {
'range': [0, 7]
},
'yaxis': {
'range': [0, 2.5]
},
'shapes': [
# Line Horizontal
{
'type': 'line',
'x0': 2,
'y0': 2,
'x1': 5,
'y1': 2,
'line': {
'color': 'rgb(50, 171, 96)',
'width': 4,
'dash': 'dashdot',
}
}
]
}
fig = {
'data': data,
'layout': layout,
}
py.iplot(fig, filename='shapes-lines')
But I wonder if there is any ways to add legend for the horizontal lines.
I think the only option at the moment is to plot it as a Scatter trace.
For example this snippet of code
import plotly.graph_objects as pgo
fig = pgo.Figure()
fig.add_traces([
pgo.Scatter(
x=[2, 3.5, 6],
y=[1, 1.5, 1],
name='Yet Another Trace'
),
pgo.Scatter(
x=[2,5],
y=[2,2],
line={
'color': 'rgb(50, 171, 96)',
'width': 4,
'dash': 'dashdot',
}, name='Horizontal Line'
)
])
fig.update_layout(**{
'xaxis': {
'range': [0, 7]
},
'yaxis': {
'range': [0, 2.5]
}
})
fig
generates this result:

Increasing opacity of area plot in plotly

How do I increase the opacity or alpha of the 'filled' area of my plot? I tried:
import pandas as pd
import plotly.offline as py
import plotly.graph_objs as go
import cufflinks as cf
from plotly import tools
plotly.offline.init_notebook_mode()
cf.go_offline()
df = pd.DataFrame(np.random.rand(10, 4), columns=['a', 'b', 'c', 'd'])
df.iplot(kind='area', fill=True, filename='cuflinks/stacked-area', opacity=.1)
but it doesn't seem to work.
There doesn't seem to be an easy built-in way of achieving this. However, a work-around is to first get the figure object of the plot, modify it to change the opacity, and then plot it.
You can get the figure object using the asFigure attribute like this:
figure = df.iplot(asFigure=True, kind='area', fill=True, filename='cuflinks/stacked-area')
The figure object in this case looks like:
Figure({
'data': [{'fill': 'tonexty',
'fillcolor': 'rgba(255, 153, 51, 0.3)',
'line': {'color': 'rgba(255, 153, 51, 1.0)', 'dash': 'solid', 'shape': 'linear', 'width': 1.3},
'mode': 'lines',
'name': 'a',
'text': '',
'type': 'scatter',
'uid': '4dcc1a3e-fba3-4a32-bb2a-40925b4fae5b',
'x': array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], dtype=int64),
'y': array([0.91229144, 0.63049138, 0.22855077, 0.13470399, 0.9114691 , 0.39640368,
0.46534334, 0.20508211, 0.00203548, 0.41343938])},
{'fill': 'tonexty',
'fillcolor': 'rgba(55, 128, 191, 0.3)',
'line': {'color': 'rgba(55, 128, 191, 1.0)', 'dash': 'solid', 'shape': 'linear', 'width': 1.3},
'mode': 'lines',
'name': 'b',
'text': '',
'type': 'scatter',
'uid': '1015b30d-7c09-456c-875c-8a211a6ebdeb',
'x': array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], dtype=int64),
'y': array([1.81115175, 1.57534372, 0.41288126, 0.38068805, 1.72268856, 0.87778503,
1.32714727, 0.848242 , 0.51605283, 0.58190402])},
{'fill': 'tonexty',
'fillcolor': 'rgba(50, 171, 96, 0.3)',
'line': {'color': 'rgba(50, 171, 96, 1.0)', 'dash': 'solid', 'shape': 'linear', 'width': 1.3},
'mode': 'lines',
'name': 'c',
'text': '',
'type': 'scatter',
'uid': '7d1852ac-b8e7-44e6-ae69-54229d7e2c83',
'x': array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], dtype=int64),
'y': array([2.79222081, 1.58812634, 1.1439478 , 1.30453731, 2.50881795, 1.67681961,
1.85609861, 1.36657712, 0.89024486, 0.82749039])},
{'fill': 'tonexty',
'fillcolor': 'rgba(128, 0, 128, 0.3)',
'line': {'color': 'rgba(128, 0, 128, 1.0)', 'dash': 'solid', 'shape': 'linear', 'width': 1.3},
'mode': 'lines',
'name': 'd',
'text': '',
'type': 'scatter',
'uid': '89b85012-fc95-487c-b7ba-9cb6c249b768',
'x': array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], dtype=int64),
'y': array([3.54740551, 1.79856232, 2.1326556 , 2.10560567, 2.64867039, 2.55519564,
2.73888819, 2.23274393, 1.16987343, 1.42794202])}],
'layout': {'legend': {'bgcolor': '#F5F6F9', 'font': {'color': '#4D5663'}},
'paper_bgcolor': '#F5F6F9',
'plot_bgcolor': '#F5F6F9',
'title': {'font': {'color': '#4D5663'}},
'xaxis': {'gridcolor': '#E1E5ED',
'showgrid': True,
'tickfont': {'color': '#4D5663'},
'title': {'font': {'color': '#4D5663'}, 'text': ''},
'zerolinecolor': '#E1E5ED'},
'yaxis': {'gridcolor': '#E1E5ED',
'showgrid': True,
'tickfont': {'color': '#4D5663'},
'title': {'font': {'color': '#4D5663'}, 'text': ''},
'zerolinecolor': '#E1E5ED'}}
})
You'll note that each trace in the data has a fillcolor attribute: 'fillcolor': 'rgba(255, 153, 51, 0.3)'. The last number is the alpha value, which you want to modify. I've made a hacky little function to update the fillcolor attribute of all traces in a figure object:
def update_opacity(figure,opacity):
for trace in range(len(figure['data'])):
# print(figure['data'][trace]['fillcolor'],'-> ',end='')
rgba_split = figure['data'][trace]['fillcolor'].split(',')
figure['data'][trace]['fillcolor'] = ','.join(rgba_split[:-1] + [' {})'.format(opacity)])
# print(figure['data'][trace]['fillcolor'])
return figure
For full opacity, you can do:
figure = update_opacity(figure,1)
Then, simply plot the result with
py.iplot(figure)
Output:

Adding node elements to json object in Python from NetworkX

I have a json object that I made using networkx:
json_data = json_graph.node_link_data(network_object)
It is structured like this (mini version of my output):
>>> json_data
{'directed': False,
'graph': {'name': 'compose( , )'},
'links': [{'source': 0, 'target': 7, 'weight': 1},
{'source': 0, 'target': 2, 'weight': 1},
{'source': 0, 'target': 12, 'weight': 1},
{'source': 0, 'target': 9, 'weight': 1},
{'source': 2, 'target': 18, 'weight': 25},
{'source': 17, 'target': 25, 'weight': 1},
{'source': 29, 'target': 18, 'weight': 1},
{'source': 30, 'target': 18, 'weight': 1}],
'multigraph': False,
'nodes': [{'bipartite': 1, 'id': 'Icarus', 'node_type': 'Journal'},
{'bipartite': 1,
'id': 'A Giant Step: from Milli- to Micro-arcsecond Astrometry',
'node_type': 'Journal'},
{'bipartite': 1,
'id': 'The Astrophysical Journal Supplement Series',
'node_type': 'Journal'},
{'bipartite': 1,
'id': 'Astronomy and Astrophysics Supplement Series',
'node_type': 'Journal'},
{'bipartite': 1, 'id': 'Astronomy and Astrophysics', 'node_type': 'Journal'},
{'bipartite': 1,
'id': 'Astronomy and Astrophysics Review',
'node_type': 'Journal'}]}
What I want to do is add the following elements to each of the nodes so I can use this data as an input for sigma.js:
"x": 0,
"y": 0,
"size": 3
"centrality": 0
I can't seem to find an efficient way to do this though using add_node(). Is there some obvious way to add this that I'm missing?
While you have your data as a networkx graph, you could use the set_node_attributes method to add the attributes (e.g. stored in a python dictionary) to all the nodes in the graph.
In my example the new attributes are stored in the dictionary attr:
import networkx as nx
from networkx.readwrite import json_graph
# example graph
G = nx.Graph()
G.add_nodes_from(["a", "b", "c", "d"])
# your data
#G = json_graph.node_link_graph(json_data)
# dictionary of new attributes
attr = {"x": 0,
"y": 0,
"size": 3,
"centrality": 0}
for name, value in attr.items():
nx.set_node_attributes(G, name, value)
# check new node attributes
print(G.nodes(data=True))
You can then export the new graph in JSON with node_link_data.

Categories

Resources