Remove whitespace below Plotly Graph Object Table - python

I'm building a simple Plotly table with margins as 0 but the output still spits out huge whitespace at the bottom of it. I tried using height to set adjustment but that's static and will not change if the number of rows change in data as recommended here
Code
import plotly.graph_objects as go
layout = go.Layout(
margin=go.layout.Margin(
l=0, #left margin
r=0, #right margin
b=0, #bottom margin
t=0, #top margin
pad=0
)
)
fig = go.Figure(data=[go.Table(header=dict(values=['A Scores', 'B Scores']),
cells=dict(values=[[100, 90, 80, 90], [95, 85, 75, 95]]))
],layout=layout)
fig.show()
Result
How do I get rid of that whitespace?

It is possible to set the graph size to the desired size in both width and height by setting the automatic setting to False.
fig.update_layout(autosize=False,
width=250,
height=120
)

Related

Fully display the amount in horizontal bar chart

With fig.update_traces(textposition="outside", textangle=0 ), chart plus text over the background will not able to fully display.
With fig.update_traces(textposition="inside", textangle=0 ), chart too short will not fully display the text amount as well.
So, is there any way to make it win-win situation?
fig = px.bar(pie_bar_gp, x='Amount', y='Product', title='Pie-Bar' ,orientation='h'
,text='Amount', text_auto=",.2f"
)
fig.update_layout(barmode="group")
fig.update_layout({
'paper_bgcolor': 'rgba(0, 0, 0, 0)',
})
chart with:
fig.update_traces(textposition="inside", textangle=0 )
fig.update_traces(textposition="outside", textangle=0 )
Yes, you can do this if you provide a list of text positions for each bar.
positions = ['inside','inside','inside','outside','inside', 'inside']
fig = px.bar(pie_bar_gp, x='Amount', y='Product',
title='Pie-Bar', orientation='h', text='Amount', text_auto=",.2f")
fig.update_traces(textposition=positions)
fig.show()
See the answer here:
https://stackoverflow.com/a/68337253/10487273
In such cases, you can pass a list of the positions you wish to display for each value. The example in the reference is forced to limit the range of the x-axis, creating the same situation as your assignment. I have set my threshold as 25, anything below that is outside and everything else is inside.
import plotly.express as px
data_Rwanda = px.data.gapminder().query("country == 'Rwanda'")
txt_position = ['outside' if x <= 25 else 'inside' for x in data_canada['lifeExp']]
fig = px.bar(data_Rwanda, x='lifeExp', y='year', orientation='h',text='lifeExp',text_auto=',.2f')
fig.update_xaxes(range=[23,50])
fig.update_traces(textposition=txt_position, textfont=dict(color='red', size=14))
fig.update_layout(autosize=True, height=600)
fig.show()

How to set annotation of hrect referenced to a secondary y axis

I'm using plotly to create some charts. I have 2 y axis available and I'm creating some horizontal rectangle referenced to a secondary y axis. Which is working fine, hrect is displayed where it has to be. But problem is that annotation linked to that hrect is not being referenced to that secondary axis. So I get a mess in representation.
This is how I define hrect
fig.add_hrect(y0=current_quantile, y1=current_quantile, fillcolor="black",
annotation_position="bottom right", annotation_text="Current performance",
line_width=1, secondary_y=True)
And this is what I get
If I modify html code and change annotation yref to y2 then it works as expected.
In my point of view this looks like a bug from plotly, if you are referring hrect to secondary axis, it has no sense that its annotation references to another axis. But I was wondering if there is some workaround which could allow me to fix this. I've tried to define annotate=dict(yref="y2") but no luck, the same with annotation_yref="y2"
According to official documentation, not sure if yref can be changed in hrect call
Thanks a lot for your help
Edit for adding a while chart representation to focus over 2 y-axis information being displayed.
started by creating a figure with two yaxes
I did find that yref="y2" is being ignored by add_hrect()
hence resolved by moving to add_shape() and add_annotation()
import pandas as pd
import plotly.express as px
import numpy as np
r = np.random.RandomState(22)
df = pd.DataFrame(
{
"x": np.linspace(0, 100, 50),
"y1": r.uniform(1, 10, 50),
"y2": r.uniform(30, 50, 50),
}
)
# create a figure with two yaxes
fig = (
px.line(df, x="x", y=["y1", "y2"])
.update_traces(yaxis="y2", selector={"name": "y2"})
.update_layout(yaxis2={"side": "right", "range": [0, 50], "overlaying":"y"})
)
current_quantile = 25
# wrong place for text
# fig.add_hrect(
# y0=current_quantile,
# y1=current_quantile,
# annotation_position="bottom right",
# annotation_text="Current performance",
# yref="y2",
# xref="paper"
# )
# correct position for text
fig.add_shape(
type="rect",
yref="y2",
xref="paper",
y0=current_quantile,
y1=current_quantile,
x0=0,
x1=1,
)
fig.add_annotation(
yref="y2",
xref="paper",
y=current_quantile,
yshift=10,
x=1,
text="Current performance",
showarrow=False
)
fig

Show name of a trace on scatterpolar chart all the time without needing to hover over it

I am trying to figure out if there is a way to have the name of a Python plotly scatterpolar trace to always be visible, rather than having to hover over each trace on the graph. This is what I have so far in terms of code.
import plotly.graph_objects as go
categories = ['Passing', 'Dribbling', 'Shooting', 'Defense', 'Fitness']
fig = go.Figure()
fig.add_traces(go.Scatterpolar(
r=[6.33, 3.71, 0, 5.45, 5],
theta=categories,
fill='toself',
name='Team Average'
))
fig.add_traces(go.Scatterpolar(
r=[9.38, 2.86, 0, 5.0, 5.6],
theta=categories,
fill='toself',
name='Player Average'
))
fig.update_layout(
polar=dict(
radialaxis=dict(
visible=False,
range=[0,10]
)
),
showlegend=False
)
fig.show()
And this is what the current scatterpolar chart looks like when I run it. As you can see, it does not show the names of each of the traces, and only appears when I hover over each trace.
With a go.Scatterpolar chart, text annotations are difficult because you will need to specify the cartesian x- and y-coordinates for the text annotations. Polar coordinates for text annotations inside the chart are not yet available, at least according to the linked Plotly forum post. While you could convert the polar coordinates of each point to x- and y-coordinates, and then add text at each of these locations, this seems like a heavy handed solution unless it's really necessary.
One compromise would be to use px.line_polar to draw the chart, and use the text argument to specify what text gets added for each point. Unfortunately you can only choose one field from your data (in your case, you can choose to display the value that you are passing to parameter r, or the category that you are passing to parameter theta).
To make px.line_polar look like go.Scatterpolar, you will want to add filling between the lines. In addition, to add the second px.line_polar chart on top of the first one, you'll need to create a new figure, then add that figure's data as a trace. You will also need to manually specify the color of the second px.line_polar chart.
import plotly.express as px
import plotly.graph_objects as go
categories = ['Passing', 'Dribbling', 'Shooting', 'Defense', 'Fitness']
fig = go.Figure()
fig = px.line_polar(
{'Team Average':[6.33, 3.71, 0, 5.45, 5], 'direction':categories},
r="Team Average",
theta="direction",
start_angle=360,
line_close=True,
text="Team Average",
)
fig2 = px.line_polar(
{'Player Average':[9.38, 2.86, 0, 5.0, 5.6], 'direction':categories},
r="Player Average",
color_discrete_sequence=["salmon"]*5,
theta="direction",
start_angle=360,
line_close=True,
text="Player Average",
)
## add fig2 to fig
fig.add_trace(fig2.data[0])
fig.update_traces(textposition='top center', fill='toself')
fig.update_layout(
polar=dict(
radialaxis=dict(
visible=False,
range=[0,10]
)
),
showlegend=False
)
fig.show()

Hoverinformation for shapes in plotly

I know there is the hovertemplate/hover_text/ option for traces (marker/line) but I cannot find such a thing for shapes.
Is there a way to have a hover text pop up when moving over a shape? Maybe a workaround?
Example:
import plotly.graph_objects as go
fig = go.Figure()
fig.add_trace(go.Scatter(
x=[1.5, 3],
y=[2.5, 2.5],
text=["Rectangle reference to the plot",
"Rectangle reference to the axes"],
mode="markers",
))
fig.add_shape(
# Rectangle reference to the plot
type="rect",
xref="paper",
yref="paper",
x0=0.25,
y0=0,
x1=0.5,
y1=0.5,
line=dict(
color="LightSeaGreen",
width=3,
),
fillcolor="PaleTurquoise",
)
When I hover over the two points, I get a hover-template with information. How can I get something similar for the shape?
It seems that it's not possible to add hoverinfo to shapes directly. But you can obtain something very close to what seems to be the desired effect through the right combination of shapes and traces. The following plot is made from specifying two rectangles in a list like:
shapes = [[2,6,2,6],
[4,7,4,7]]
The rest of the code snippet is set up to be flexible with regards to the number of shapes, and the colors assigned to them and the corresponding traces to make that little dot in the lower right corners of the shapes.
Plot:
If this is something you can use, we can discuss ways to edit what is being displayed in the hoverinfo.
Complete code:
# Imports
import pandas as pd
#import matplotlib.pyplot as plt
import numpy as np
import plotly.graph_objects as go
import plotly.express as px
# shape definitions
shapes = [[2,6,2,6],
[4,7,4,7]]
# color management
# define colors as a list
colors = px.colors.qualitative.Plotly
# convert plotly hex colors to rgba to enable transparency adjustments
def hex_rgba(hex, transparency):
col_hex = hex.lstrip('#')
col_rgb = list(int(col_hex[i:i+2], 16) for i in (0, 2, 4))
col_rgb.extend([transparency])
areacol = tuple(col_rgb)
return areacol
rgba = [hex_rgba(c, transparency=0.4) for c in colors]
colCycle = ['rgba'+str(elem) for elem in rgba]
# plotly setup
fig = go.Figure()
# shapes
for i, s in enumerate(shapes):
fig.add_shape(dict(type="rect",
x0=s[0],
y0=s[2],
x1=s[1],
y1=s[3],
layer='above',
fillcolor=colCycle[i],
line=dict(
color=colors[i],
width=3)))
# traces as dots in the lower right corner for each shape
for i, s in enumerate(shapes):
fig.add_trace(go.Scatter(x=[s[1]], y=[s[2]], name = "Hoverinfo " +str(i + 1),
showlegend=False,
mode='markers', marker=dict(color = colors[i], size=12)))
# edit layout
fig.update_layout(yaxis=dict(range=[0,8], showgrid=True),
xaxis=dict(range=[0,8], showgrid=True))
fig.show()
I thought of a solution I am happy with.
Simply draw a shape. You won't be able to see a hover text. However, if you add a trace with a fill on top of the shape, then set the trace to opacity=0 you will see the hover text from the trace pop up when moving over the shape.
Again, thanks for your responses!
import plotly.graph_objects as go
# Draw shape (you won't be able to add a hover text for it)
fig = go.Figure()
fig.add_shape(
type="rect",
x0=0, y0=0,
x1=4, y1=3,
fillcolor='LightSkyBlue',
line_color='Blue',
name='Shape 1'
)
# Adding a trace with a fill, setting opacity to 0
fig.add_trace(
go.Scatter(
x=[0,0,4,4,0],
y=[0,3,3,0,0],
fill="toself",
mode='lines',
name='',
text='Custom text on top of shape',
opacity=0
)
)
fig.show()

Missing title displayed in plotly

I am trying to change the background color in plotly, but after using layout function, I'm missing title from plotly.
layout = Layout(
paper_bgcolor='rgba(0,0,0,0)',
plot_bgcolor='rgba(0,0,0,0)'
)
data['Country'].value_counts()[:10][::-1].iplot(kind="barh",bargap=.5, title="Top 10 countries faced terrorist attacks", colors="#182844", layout=layout)
You'll be better off using go.Figure() instead of iplot(). It's hard to make out what the problem is with your plot, but with an example from plot.ly/python/horizontal-bar-charts/ you can easily set both title and background color using fig.update_layout()
Plot:
Code:
import plotly.graph_objects as go
fig = go.Figure(go.Bar(
x=[20, 14, 23],
y=['giraffes', 'orangutans', 'monkeys'],
orientation='h'))
fig.update_layout(title='Title',
paper_bgcolor='rgba(0,0,0,0)',
plot_bgcolor='rgba(0,0,0,0)')
fig.show()
I tried adding layout the the iplot itself and it worked. We can also adjust margin along with it.
Sample Code:
data['Nationality'].value_counts()[0:10][::-1].iplot(kind="barh",bargap=.5,
colors="mediumorchid", layout=Layout(paper_bgcolor='rgba(0,0,0,0)',
plot_bgcolor='rgba(0,0,0,0)',
width=800, height=500,
title='Nationality of terrorist attacks',
margin=dict(l=200, r=50, t=80, b=50)))
enter image description here

Categories