How to fix Plotly Heatmap block size? - python

Here is my HeatMap plot function :
def plot_heatmap(alphas, k_list, title_prefix="", years=["Y2013", "Y2014"]):
data = [
Heatmap(
name="",
z= alphas,
x=years,
y=k_list,
hoverongaps = False,
zauto=False,
zmin=zmin,
zmax=zmax,
colorscale= color_custom,
colorbar = dict(
title="Alpha Value",
thicknessmode="pixels",
thickness=50,
yanchor="top",
y=1,
len=480,
lenmode="pixels",
ticks="outside",
dtick=zmax / 10
)
)
]
fig = Figure(
data=data,
layout=Layout(
width = 640,
height = round(60 * len(k_list)) if round(60 * len(k_list)) > 640 else 640,
# autosize = True,
title=title_prefix + " | HeatMap : alphas",
)
)
fig.data[0]['hoverinfo'] = 'all'
fig['layout']['yaxis']['scaleanchor']='x'
iplot(fig)
Right now my work around is height = round(60 * len(k_list)) if round(60 * len(k_list)) > 640 else 640, in the *Layout object.
Result is like this : (I don't want to see the grey parts on the plot, how can I do that)

I think what's happening here is that for some reason plotly takes your years input to be numerical, you can make this variable explicitly categorical by adding
fig['layout']['xaxis']['type'] = 'category'

I meet the same problem while setting fixed aspect ratio to figure.
Found the answer here
https://plotly.com/python/axes/#fixed-ratio-axes-with-compressed-domain
fig['layout']['xaxis']['constrain'] = 'domain'

do this :
fig.update_xaxes(tickson='boundaries')
fig.update_yaxes(tickson='boundaries')

Related

Python Bokeh Not Changing the Colour of the Text when Updating

I am trying to update the colour of a text on a plot I am creating.
The code looks like this:
plot = figure(
x_axis_location="above", tools="hover,save",
x_range=list(reversed(names)), y_range=names,
tooltips = [('names', '#yname, #xname'), ('count', '#count')]
)
plot.width = 4500
plot.height = 4500
plot.grid.grid_line_color = 'pink'
plot.axis.axis_line_color = 'pink'
plot.axis.major_tick_line_color = 'white'
plot.axis.major_tick_line_color = None
plot.axis.major_label_text_font_size = "22px"
plot.axis.major_label_standoff = 3
plot.xaxis.major_label_orientation = np.pi/2
plot.rect('xname', 'yname', 1.0, 1.0, source=data,
color='colors', alpha='alphas', line_color=None,
hover_line_color='pink', hover_color='colors'
)
save(plot, title='plot.html', filename="plot.html")
According to the documentation it should be pretty simple:
plot.axis.axis_label_text_color = 'white'
However, Bokeh refuses to change the color of any of the axis texts. I'm pretty befuddled on how to get the axis labels to be white or what is going on here?
plot.xaxis.axis_label_text_color = 'white'
plot.yaxis.major_label_text_color = 'white'
It's this. The documentation for this is funky.

Hiding Duplicate Legend in Plotly

I'm new in using plotly and I'm trying to make a 2 different graph and show them individually through button; however, when I make it, the legends duplicated, resulting to a bad visualization of the data. Here's the code that I'm running right now:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import plotly as ply
import plotly.express as px
import plotly.graph_objects as go
url = "https://raw.githubusercontent.com/m23chaffee/DS100-Repository/main/Aluminum%20Alloy%20Data%20Set.csv"
alloy = pd.read_csv('https://raw.githubusercontent.com/m23chaffee/DS100-Repository/main/Aluminum%20Alloy%20Data%20Set.csv')
del alloy['temper']
alloy = alloy.rename(columns={'aluminum_alloy':'Alloy Number',
'modulus_elastic': 'Elastic Modulus',
'modulus_shear': 'Shear Modulus',
'strength_yield': 'Yield Strength',
'strength_tensile': 'Tensile Strength'
})
bar1 = px.bar(alloy,
x = "Alloy Number",
y = ["Elastic Modulus", "Shear Modulus","Yield Strength","Tensile Strength"],
barmode = 'group',
width = 1100,
height =500,
orientation = 'v',
color_discrete_sequence = px.colors.qualitative.Pastel,
labels={"value": "Data Values"},
template = 'seaborn').update_traces(legendgroup="group").update_layout(showlegend=False)
line1 = px.line(alloy,
x = "Alloy Number",
y = ["Elastic Modulus", "Shear Modulus","Yield Strength","Tensile Strength"],
width = 1100,
height =500,
orientation = 'v',
color_discrete_sequence = px.colors.qualitative.Pastel,
labels={"value": "Data Values"},
template = 'seaborn').update_traces(legendgroup="group", visible = 'legendonly').update_layout(showlegend=False)
# Add buttom
fig.update_layout(
updatemenus=[
dict(
type = "buttons",
direction = "left",
buttons=list([
dict(
args=['type', 'bar'],
label="Bar Graph",
method="restyle",
),
dict(
args=["type", "line"],
label="Line Graph",
method="restyle"
)
]),
pad={"r": 10, "t": 10},
showactive=True,
x=0.11,
xanchor="left",
y=1.1,
yanchor="middle"
),
]
)
fig.show()
and the result of the image would look like this:
Result of the code above
Attempted Solution
I tried to hide it using traces and in the documentation but it seems it didn't work out for me. I also found a similar stackoverflow post 8 years ago, tried it, and it didn't make any changes in my graph.

Altair : Make Interval Selection Line plot with dual axis and datetime x axis

I am trying to make a dual y axis line plot with date time index as x axis, with interval selection, so far :
#base encoding the X-axis
brush = alt.selection(type='interval', encodings=['x'])
base = alt.Chart(yData.reset_index())
base = base.encode(alt.X('{0}:T'.format(yData.index.name),
axis=alt.Axis(title=yData.index.name)))
py = base.mark_line()
py = py.encode(alt.X('date:T',scale = alt.Scale(domain = brush)),
alt.Y('plotY', axis=alt.Axis(title='ylabel1')))
py = py.properties(width = 700, height = 230)
px = base.mark_line()
px = px.encode(alt.Y('plotX1', axis=alt.Axis(title='ylabel2')))
px = px.properties(width = 700, height = 230)
upper = (py + px).resolve_scale(y='independent')
lower = upper.copy()
lower = lower.properties(height=20).add_selection(brush)
p = alt.vconcat(upper, lower).configure_concat(spacing=0)
p
If I try to produce p I am getting the following error :
Javascript Error: Duplicate signal name: "selector045_x"
This usually means there's a typo in your chart specification. See the JavaScript console for the full traceback
If I try to produce upper I get:
My dataframe :
Any idea how can I get interval selection here?
Also I keep getting this error while working with Altair, any idea how can I debug this?? I have no experience in java, and am using a Mac.
EDIT
After adding the selection to only one of the subplots,
brush = alt.selection(type='interval', encodings=['x'])
base = alt.Chart(yData.reset_index())
base = base.encode(alt.X('{0}:T'.format(yData.index.name),
axis=alt.Axis(title=yData.index.name)))
py = base.mark_line()
py = py.encode(alt.X('date:T',scale = alt.Scale(domain = brush)),
alt.Y('plotY', axis=alt.Axis(title='ylabel1')))
py = py.properties(width = 700, height = 230).add_selection(brush)
px = base.mark_line()
px = px.encode(alt.Y('plotX1', axis=alt.Axis(title='ylabel2')))
px = px.properties(width = 700, height = 230)
upper = (py + px).resolve_scale(y='independent')
lower = upper.copy()
lower = lower.properties(height=20)
p = alt.vconcat(upper, lower).configure_concat(spacing=0)
p
I am getting this :
(1) The selection isn't working
(2) And somehow i am getting an exact replica of upper for the lower plot
**EDIT -- This made it work **
brush = alt.selection(type='interval', encodings=['x'])
base = alt.Chart(yData.reset_index())
base = base.encode(alt.X('{0}:T'.format(yData.index.name),
axis=alt.Axis(title=yData.index.name)))
py = base.mark_line(color='orange')
py = py.encode(alt.X('date:T',scale = alt.Scale(domain = brush)),
alt.Y('plotY', axis=alt.Axis(title='ylabel1')),
)
py = py.properties(width = 700, height = 230)
px = base.mark_line()
px = px.encode(alt.X('date:T',scale = alt.Scale(domain = brush)),
alt.Y('plotX1', axis=alt.Axis(title='ylabel2')))
px = px.properties(width = 700, height = 230)
# upper = px
upper = (py + px).resolve_scale(y='independent')
lower = px.copy()
lower = lower.properties(height=20).add_selection(brush)
p = alt.vconcat(upper, lower).configure_concat(spacing=0)
p
Add the selection to just px or py instead. If you add the same selection to both subcharts in a layer, it results in this error. This is a bug that should probably be fixed in Altair.
To be more concrete, your code should look like this:
# ...
px = px.properties(width = 700, height = 230).add_selection(brush) # add selection here
# ...
lower = lower.properties(height=20) # not here
# ...

Python - plotly hover icon not working

As far as I'm aware, I've copied the documentation exactly. I basically used the documentation code and tweaked it for my purposes. But when I run this bit of code, no hover feature with text appears on my plot.
#Initialize df
aviation_data = pd.DataFrame(columns=["Latitude","Longitude","Fatalities"])
aviation_data["Latitude"] = [40.53666,60.94444]
aviation_data["Longitude"] = [-81.955833,-159.620834]
aviation_data["Fatalities"] = [True,False]
#Initialize colorscale
scl = [[0,"rgb(216,15,15)"],[1,"rgb(5,10,172)"]]
#Initialize text data
text_df = "Fatal: " + aviation_data["Fatalities"].apply(lambda x: str(np.bool(x))) + '<br>' + \
"Latitude: " + aviation_data["Latitude"].apply(lambda x: str(x)) + '<br>' + \
"Longitude" + aviation_data["Longitude"].apply(lambda x: str(x))
#Initialize data
data = [ dict(
type = 'scattergeo',
locationmode = 'USA-states',
lon = aviation_data["Longitude"],
lat = aviation_data["Latitude"],
text = text_df,
mode = 'markers',
marker = dict(
size = 5,
opacity = 0.5,
reversescale=True,
autocolorscale=False,
symbol = 'circle',
line = dict(
width=1,
color='rgba(102, 102, 102)'
),
colorscale = scl,
cmin = 0,
color = aviation_data["Fatalities"].astype(int),
cmax = 1
))]
#Initialize layout
layout = dict(
title ='Aviation Incidents for the Years 2014-2016<br>\
(red indicates fatal incident, blue indicates non-fatal)',
geo = dict(
scope='usa',
projection=dict(type='albers usa'),
showland = True,
landcolor = "rgb(206, 206, 206)",
countrywidth = 0.5,
subunitwidth = 0.5
),
)
#Plot
fig = dict(data=data,layout=layout)
iplot(fig,validate=False)
Anyone know why my hover text isn't showing up?
In the last line of code you need to call this:
plotly.offline.plot(fig, validate=False)
Instead of:
iplot(fig, validate=False)
Also do not forget import plotly:
import plotly
Hope this will help

Adding hover tool tip to bokeh histogram

I have created a histogram in bokeh using the following code:
TOOLS="pan,wheel_zoom,box_zoom,reset,hover"
for column in valid_columns:
output_file_name = str( file_name + column + ".html" )
data_values = stats[ column ].tolist()
output_file( output_file_name )
histogram, edges = np.histogram( data_values, bins=50 )
source = ColumnDataSource(
data = dict( data_value = data_values ) )
p1 = figure( title = column, background_fill="#E8DDCB", tools=TOOLS )
p1.quad( top = histogram, bottom = 0, left = edges[ :-1 ], right = edges[ 1: ],
fill_color = "#036564", line_color = "#033649" )
hover = p1.select(dict(type=HoverTool))
hover.tooltips = [ ( "Value", "#data_value" ) ]
show( p1 )
print( "Saved Figure to ", output_file_name )
where valid columns are a list of all columns I want examined within a pandas dataframe. I am trying to add a hover tool tip which will display the number of items stored in each bin but I have not be able to do so. Any help would be appreciated.
If you prefer to not use a ColumnDataSource, you can replace #data_value with #top and it should work with minimal editing:
hover = HoverTool(tooltips = [('Value', '#top')])
p.add_tools(hover)
i.e. editing the example histogram.py in this way also works:
from bokeh.models import HoverTool
def make_plot(title, hist, edges, x, pdf, cdf):
p = figure(title=title, tools='', background_fill_color="#fafafa")
p.quad(top=hist, bottom=0, left=edges[:-1], right=edges[1:],
fill_color="navy", line_color="white", alpha=0.5)
p.line(x, pdf, line_color="#ff8888", line_width=4, alpha=0.7, legend_label="PDF")
p.line(x, cdf, line_color="orange", line_width=2, alpha=0.7, legend_label="CDF")
p.y_range.start = 0
p.legend.location = "center_right"
p.legend.background_fill_color = "#fefefe"
p.xaxis.axis_label = 'x'
p.yaxis.axis_label = 'Pr(x)'
p.grid.grid_line_color="white"
hover = HoverTool(tooltips = [('Density', '#top')])
p.add_tools(hover)
return p
It looks like you are missing a couple of things:
Have a source of the same length as your histogram, not your data_values. To be more concrete, I think you want your source to be:
source = ColumnDataSource( data = dict( data_value = histogram ) )
Add the source to your p1.quad call, i.e.
p1.quad( top = histogram, bottom = 0, left = edges[ :-1 ], right = edges[ 1: ],
fill_color = "#036564", line_color = "#033649", source = source )

Categories