Plotly volume frames (four-dimensional slices) - python

Can this example be adapted to show three-dimensional slices instead of two-dimensional ones?
I tried replacing Surface with Volume:
a, b, c = data.shape[1:] # data.ndim == 4
X, Y, Z = np.mgrid[-1:1:a*1j, -1:1:b*1j, -1:1:c*1j]
fig = go.Figure(frames=[go.Frame(data=go.Volume(
x=X.flatten(),
y=Y.flatten(),
z=Z.flatten(),
value=data[k].flatten(),
opacity=.25,
surface_count=12,
colorscale='jet',
), name=str(k)) for k in range(len(data))])
And Volume works fine on its own, but I get empty frames with the above.

Thanks to #empet at Plotly Community:
import numpy as np
import plotly.graph_objects as go
from plotly.offline import plot # for IDE use
vol4 = np.random.randint(0, 27, size=(6, 5, 7, 4))
a, b, c = vol4.shape[1:]
X, Y, Z = np.mgrid[-1:1:a*1j, -1:1:b*1j, -1:1:c*1j]
fig = go.Figure(go.Volume(x=X.flatten(),
y=Y.flatten(),
z=Z.flatten(),
value=vol4[0].flatten(),
opacity=.25,
surface_count=12,
colorscale='turbo',
colorbar_len=0.8
))
frames=[go.Frame(data=go.Volume(
value=vol4[k].flatten()),
name=str(k)) for k in range(len(vol4))]
updatemenus = [dict(
buttons = [
dict(
args = [None, {"frame": {"duration": 100, "redraw": True},
"fromcurrent": True, "transition": {"duration": 0}}],
label = "Play",
method = "animate"
),
dict(
args = [[None], {"frame": {"duration": 0, "redraw": False},
"mode": "immediate",
"transition": {"duration": 0}}],
label = "Pause",
method = "animate"
)
],
direction = "left",
pad = {"r": 10, "t": 87},
showactive = False,
type = "buttons",
x = 0.21,
xanchor = "right",
y = -0.075,
yanchor = "top"
)]
sliders = [dict(steps = [dict(method= 'animate',
args= [[f'{k}'],
dict(mode= 'immediate',
frame= dict(duration=100, redraw=True),
transition=dict(duration= 0))
],
label=f'{k+1}'
) for k in range(len(vol4))],
active=0,
transition= dict(duration=0),
x=0, # slider starting position
y=0,
currentvalue=dict(font=dict(size=12),
prefix='frame: ',
visible=True,
xanchor= 'center'
),
len=1.0) #slider length
]
fig.update_layout(width=700, height=700, updatemenus=updatemenus, sliders=sliders)
fig.update(frames=frames)
plot(fig, auto_open=True)

Related

How to make a plotly graph wider and higher? [duplicate]

I have made a scatter plot using matplotlib and Plotly. I want the height, width and the markers to be scatter as in matplotlib plot. Please see the attached plots.
I used the following code in Plotly
import plotly
import plotly.plotly as py
from plotly.graph_objs import Scatter
import plotly.graph_objs as go
trace1 = go.Scatter(
x=x1_tsne, # x-coordinates of trace
y=y1_tsne, # y-coordinates of trace
mode='markers ', # scatter mode (more in UG section 1)
text = label3,
opacity = 1,
textposition='top center',
marker = dict(size = 25, color = color_4, symbol = marker_list_2, line=dict(width=0.5)),
textfont=dict(
color='black',
size=18, #can change the size of font here
family='Times New Roman'
)
)
layout = {
'xaxis': {
'showticklabels': False,
'showgrid': False,
'zeroline': False,
'linecolor':'black',
'linewidth':2,
'mirror':True,
'autorange':False,
'range':[-40, 40][![enter image description here][1]][1]
},
'yaxis': {
'showticklabels': False,
'showgrid': False,
'zeroline': False,
'linecolor':'black',
'linewidth':2,
'mirror':True,
'autorange':False,
'range':[-40, 40]
}
}
data = [trace1]
fig = go.Figure(
data= data,
layout= layout)
py.iplot(fig)
I try to tune the range but did not help. In addition, I use Autorange that did not help. Could you please help me with this.
I want the image as
##update: This can be done by the following code. I am updating this in the question:
trace1 = go.Scatter(
x=x1_tsne, # x-coordinates of trace
y=y1_tsne, # y-coordinates of trace
mode='markers +text ', # scatter mode (more in UG section 1)
text = label3,
opacity = 1,
textposition='top center',
marker = dict(size = 25, color = color_4, symbol = marker_list_2, line=dict(width=0.5)),
textfont=dict(
color='black',
size=18, #can change the size of font here
family='Times New Roman'
)
)
data = [trace1]
layout = go.Layout(
autosize=False,
width=1000,
height=1000,
xaxis= go.layout.XAxis(linecolor = 'black',
linewidth = 1,
mirror = True),
yaxis= go.layout.YAxis(linecolor = 'black',
linewidth = 1,
mirror = True),
margin=go.layout.Margin(
l=50,
r=50,
b=100,
t=100,
pad = 4
)
)
fig = go.Figure(data=data, layout=layout)
py.iplot(fig, filename='size-margins')
Have you considered to use
fig.update_layout(
autosize=False,
width=800,
height=800,)
and eventually reduce the size of your marker?
UPDATE
Full Code
import plotly.graph_objs as go
trace1 = go.Scatter(
x=x1_tsne, # x-coordinates of trace
y=y1_tsne, # y-coordinates of trace
mode='markers +text ', # scatter mode (more in UG section 1)
text = label3,
opacity = 1,
textposition='top center',
marker = dict(size = 12, color = color_4, symbol = marker_list_2, line=dict(width=0.5)),
textfont=dict(
color='black',
size=18, #can change the size of font here
family='Times New Roman'
)
)
data = [trace1]
layout = go.Layout(
autosize=False,
width=1000,
height=1000,
xaxis= go.layout.XAxis(linecolor = 'black',
linewidth = 1,
mirror = True),
yaxis= go.layout.YAxis(linecolor = 'black',
linewidth = 1,
mirror = True),
margin=go.layout.Margin(
l=50,
r=50,
b=100,
t=100,
pad = 4
)
)
fig = go.Figure(data=data, layout=layout)

Plotly add border to a specific subplot

So I need to draw a graph with two subplots, and want to add borders to the one above. I am using plotly, but failed to find a way to do so. The borders here are essentially the solid line along the axes, but as a rectangle. Does anyone know how to add borders (axes) to a specific subplot?
My code:
#random generate points#
x1=np.random.normal(50, 10, 1000)
x2=np.random.normal(30, 10, 1000)
x3=np.random.normal(70, 10, 1000)
x1_kde=gaussian_kde(x1)
x1_range=linspace(min(x1), max(x1),len(x1))
x1_evaluated=x1_kde.evaluate(x1_range)
x2_kde=gaussian_kde(x2)
x2_range=linspace(min(x2), max(x2),len(x2))
x2_evaluated=x2_kde.evaluate(x2_range)
x3_kde=gaussian_kde(x3)
x3_range=linspace(min(x3), max(x3),len(x3))
x3_evaluated=x3_kde.evaluate(x3_range)
def bedslistmaker(x,n):
listofbeds = [x] * n
return listofbeds
x1_beds=bedslistmaker('bed 1',len(x1))
x2_beds=bedslistmaker('bed 2',len(x2))
x3_beds=bedslistmaker('bed 3',len(x3))
First three traces for the histogram (KDE)
trace1 = go.Scatter(x=x1_range,y=x1_evaluated,xaxis="x2", yaxis="y2", \
mode='lines',line={'color': '#377e22','width': 1},marker={'color':'#377e22'},\
fill='tozeroy',fillcolor='rgba(55, 126, 34, 0.25)',showlegend=True,name='x1')
trace2 = go.Scatter(x=x2_range,y=x2_evaluated,xaxis="x2", yaxis="y2", \
mode='lines',line={'color': '#0480A6','width': 1},marker={'color':'#0480A6'},\
fill='tozeroy',fillcolor='rgba(4, 128, 166, 0.25)',showlegend=True,name='x2')
trace3 = go.Scatter(x=x3_range,y=x3_evaluated,xaxis="x2", yaxis="y2", \
mode='lines',line={'color': '#FF0000','width': 1},marker={'color':'#FF0000'},\
fill='tozeroy',fillcolor='rgba(255, 0, 0, 0.25)',showlegend=True,name='x3')
Last three for the sticks below
trace4=go.Scatter(x=x1,y=x1_beds,mode="markers",xaxis= "x1", yaxis= "y1",marker={
"color": "#377e22",
"symbol": "line-ns-open"},
text=None,
showlegend=False)
trace5=go.Scatter(x=x2,y=x2_beds,mode="markers",xaxis= "x1", yaxis= "y1",marker={
"color": "#0480A6",
"symbol": "line-ns-open"
}, text=None,showlegend=False)
trace6=go.Scatter(x=x3,y=x3_beds,mode="markers",xaxis= "x1", yaxis= "y1",marker={
"color": "#FF0000",
"symbol": "line-ns-open"
}, text=None,showlegend=False)
data=[trace1,trace2,trace3,trace4,trace5,trace6]
layouts
layout = go.Layout(
xaxis1=go.layout.XAxis(
domain=[0.00, 1],
anchor="x1",
showticklabels=False),
yaxis1=go.layout.YAxis(
domain=[0.01, 0.17],
anchor="y1",
showticklabels=False,
title=go.layout.yaxis.Title(
font=dict(
family='Courier New, monospace',
size=15,
color='#7f7f7f'))),
yaxis2=go.layout.YAxis(
domain=[0.17, 1],
anchor="y2",
showticklabels=True,
title=go.layout.yaxis.Title(
text='Probability Density',
font=dict(
family='Courier New, monospace',
size=15,
color='#7f7f7f'))),
)
fig=go.Figure(data=data,layout=layout)
#fig.layout.update(showlegend=False)
fig.layout.update(template='plotly_white')#barmode='overlay'
fig.update_layout(
legend=go.layout.Legend(
x=0.73,
y=0.97,
traceorder="normal",
font=dict(
family="Courier New,monospace",
size=10,
color="#7f7f7f"
),
#bgcolor="white",
bordercolor="black",
borderwidth=1
)
)
fig.update_layout(
margin=dict(l=80, r=80, t=50, b=80))
fig.layout.update(template='plotly_white')#barmode='overlay'
fig.update_layout(autosize=False,width=1000,height=618)
fig.show()
You can set axis lines with so called mirrors for any subplot by referencing their position with row, col like this:
fig.update_xaxes(showline = True, linecolor = 'black', linewidth = 1, row = 1, col = 1, mirror = True)
fig.update_yaxes(showline = True, linecolor = 'black', linewidth = 1, row = 1, col = 1, mirror = True)
Plot:
Code:
from plotly.subplots import make_subplots
import plotly.graph_objects as go
fig = make_subplots(rows=2, cols=1)
fig.append_trace(go.Scatter(
x=[3, 4, 5],
y=[1000, 1100, 1200],
), row=1, col=1)
fig.append_trace(go.Scatter(
x=[2, 3, 4],
y=[100, 110, 120],
), row=2, col=1)
fig.update_xaxes(showline = True, linecolor = 'black', linewidth = 1, row = 1, col = 1, mirror = True)
fig.update_yaxes(showline = True, linecolor = 'black', linewidth = 1, row = 1, col = 1, mirror = True)
fig.update_layout(height=600, width=600, title_text="Border for upper subplot")
f = fig.full_figure_for_development(warn=False)
fig.show()

Color specific points in a plotly express strip plot

Let's take this sample dataframe :
import random
df=pd.DataFrame({'Id':list(range(1,101)), 'Value':[random.randint(0,50) for i in range(100)]})
I would like to create a plotly express strip plot in which id 5 and 10 are colored in red and the others in blue. I built the following function :
import plotly.express as px
def strip_plotly(df,col_value,col_hover=[],col_color=None,L_color=[]):
if col_color is not None :
L_color = ["red" if i in L_color else "blue" for i in df[col_color].values]
else :
L_color = ["blue"]*len(df.index)
fig = px.strip(df, y=col_value,hover_data = col_hover,color_discrete_sequence = L_color)
fig.update_layout({
'plot_bgcolor': 'rgba(0,0,0,0)',
'paper_bgcolor': 'rgba(0,0,0,0)',
},
hoverlabel=dict(
#bgcolor="white",
font_size=12,
#font_family="Rockwell"
),
xaxis={
'title':"x",
#'type':'log'
},
yaxis={'title':"y"},
title={
'text': "strip plot for stackoverflow",
#'y':0.95,
'x':0.5,
'xanchor': 'center',
'yanchor': 'top'}
)
fig.update_xaxes(showspikes=True, spikecolor = 'black', showline=True, linewidth=1,linecolor='black',
ticks = "outside", tickwidth = 1, tickcolor = 'black',ticklen = 5)
fig.update_yaxes(showspikes=True, spikecolor = 'black', showline=True, linewidth=1,linecolor='black',
ticks = "outside", tickwidth = 1, tickcolor = 'black',ticklen = 5)
fig.show()
But when I run the function :
strip_plotly(df,"Value",col_hover=["Id"],col_color="Id",L_color=[5,10])
I get only blue points (ids 5 and 10 are not red). Would you please explain me what's wrong ?
have reduced size of data frame just to make it clear red points are there...
you need two traces as color is only one per trace https://plotly.github.io/plotly.py-docs/generated/plotly.graph_objects.box.marker.html
to make traces line up have also defined offsetgroup
import random
import plotly.express as px
import numpy as np
import pandas as pd
df=pd.DataFrame({'Id':list(range(1,21)), 'Value':[random.randint(0,50) for i in range(20)]})
def strip_plotly(df,col_value,col_hover=[],col_color=None,L_color=[]):
L_color = np.where(df["Id"].isin([5,10]), "red", "blue")
# need two traces as color is in marker https://plotly.github.io/plotly.py-docs/generated/plotly.graph_objects.box.marker.html
fig = px.strip(df.loc[L_color=="blue"], y=col_value,hover_data = col_hover,color_discrete_sequence = ["blue"])
fig = fig.add_traces(px.strip(df.loc[L_color=="red"], y=col_value,hover_data = col_hover,color_discrete_sequence = ["red"]).data)
fig = fig.update_traces(offsetgroup="1")
fig.update_layout({
'plot_bgcolor': 'rgba(0,0,0,0)',
'paper_bgcolor': 'rgba(0,0,0,0)',
},
hoverlabel=dict(
#bgcolor="white",
font_size=12,
#font_family="Rockwell"
),
xaxis={
'title':"x",
#'type':'log'
},
yaxis={'title':"y"},
title={
'text': "strip plot for stackoverflow",
#'y':0.95,
'x':0.5,
'xanchor': 'center',
'yanchor': 'top'}
)
fig.update_xaxes(showspikes=True, spikecolor = 'black', showline=True, linewidth=1,linecolor='black',
ticks = "outside", tickwidth = 1, tickcolor = 'black',ticklen = 5)
fig.update_yaxes(showspikes=True, spikecolor = 'black', showline=True, linewidth=1,linecolor='black',
ticks = "outside", tickwidth = 1, tickcolor = 'black',ticklen = 5)
return fig.show()
strip_plotly(df,"Value",col_hover=["Id"],col_color="Id",L_color=[5,10])
Here's a much simpler solution.
Create a 'color' column with the desired color
Assign colors based on the values of that column (creates a separate trace for each color)
Overlay traces on top of each other
df=pd.DataFrame({'Id':list(range(1,101)), 'Value':[random.randint(0,50) for i in range(100)]})
df['color'] = np.where(df['Id'].isin([5,10]), 'red', 'blue')
fig = px.strip(df, y='Value', color='color')
fig.update_traces(offsetgroup=0)
fig.show()

Selecting multiple buttons at once in a plotly graph

I've been able to figure out how to update a Plotly graph with new data using buttons. That is, if I select a certain button (say X1 in the example below), the plot will change so that it'll plot that variable, etc.
However, I want to be able to select multiple buttons at once. For example, I want to be able to select X1 and X2 and plot both on the chart.
I haven't been able to make any progress on this, so I was hoping someone could provide some clues on a way forward.
import plotly
import plotly.graph_objs as go
import numpy as np
import pandas as pd
plotly.offline.init_notebook_mode(connected=True)
x0 = np.linspace(0,99,100)
y0 = np.random.normal(2, 0.4, 100)
y1 = np.random.normal(2, 0.4, 100)
y2 = np.random.normal(2, 0.4, 100)
trace0 = go.Scatter(x = x0, y = y0)
trace1 = go.Scatter(x = x0, y = y1, visible = False)
trace2 = go.Scatter(x = x0, y = y2, visible = False)
data = [trace0, trace1, trace2]
button1 = dict(label = 'X0',
method = 'update',
args = [{'visible': [True, False, False]}])
button2 = dict(label = 'X1',
method = 'update',
args = [{'visible': [False, True, False]}])
button3 = dict(label = 'X2',
method = 'update',
args = [{'visible': [False, False, True]}])
updatemenus = list([
dict(type="buttons", active = 0,
buttons = [button1, button2, button3], yanchor = 'top')])
layout = dict(title='Chart', showlegend=False,
updatemenus=updatemenus)
fig = dict(data=data, layout=layout)
plotly.offline.iplot(fig)

How to align trace text to center in a stacked horizontal bar chart

I have a stacked horizontal bar and I want text defined for each trace to be placed at the center of the corresponding bar. I can't find an attribute that sets this without using anotations, but I'd like to use "text" for each trace and just be able to align it.
I'm using Plotly 3.4.1 with Jupyter (Plotly offline).
Couldn't find any documentation about how to do this except trying to do this with annotations, which look like a more suitable solution if I want to pinpoint an explicit coordinate. What I want is a much simpler (something like "align": "center"), but couldn't find any attribute for this under go.Bar
Just want the "80", "20" to appear at the center instead of aligned to the right
from plotly.offline import iplot, plot, init_notebook_mode
import plotly.graph_objs as go
def getStackedSentimentHbar():
trace0 = go.Bar(
y=["A","B"],
x=[20,80],
orientation = 'h',
text=["20","80"],
textposition="inside",
hoverinfo = "none",
)
trace1 = go.Bar(
y=["A","B"],
x=[80,20],
orientation = 'h',
text=["80","20"],
textposition="inside",
hoverinfo = "none",
)
data = [trace0,trace1]
layout = go.Layout(
barmode='stack',
showlegend=False,
xaxis=dict(
showgrid=False,
zeroline=False,
showline=False,
ticks='',
showticklabels=False
),
yaxis=dict(
showgrid=False,
zeroline=False,
showline=False,
ticks='',
showticklabels=True
),
margin = dict(
l = 200,
r = 50,
b = 50,
t = 50,
pad = 10
),
font=dict(
family='Heebo',
size=18,
color='#000000'
)
)
fig = go.Figure(data=data, layout=layout)
return fig
init_notebook_mode()
fig = getStackedSentimentHbar()
iplot(fig)
As far as I know there is no such parameter in Plotly but we can always hack to Plotly :)
Let's just duplicate all x- and y-values but leave the text as it is.
In the code below there are two functions, getStackedSentimentHbar and getStackedSentimentHbarCentered. The first one returns the original graph, the second returns the graph with the (almost) centered labels.
from plotly.offline import iplot, plot, init_notebook_mode
import plotly.graph_objs as go
LAYOUT = go.Layout(
barmode='stack',
showlegend=False,
xaxis=dict(
showgrid=False,
zeroline=False,
showline=False,
ticks='',
showticklabels=False
),
yaxis=dict(
showgrid=False,
zeroline=False,
showline=False,
ticks='',
showticklabels=True
),
margin = dict(
l = 200,
r = 50,
b = 50,
t = 50,
pad = 10
),
font=dict(
family='Heebo',
size=18,
color='#000000'
)
)
def getStackedSentimentHbar(values):
data = []
for i, x in enumerate(values['x']):
trace = go.Bar(
x=x,
y=values['y'][i],
orientation='h',
text=x,
textposition='inside',
hoverinfo = 'none',
)
data.append(trace)
fig = go.Figure(data=data, layout=LAYOUT)
return fig
def getStackedSentimentHbarCentered(values):
data = []
for i, x in enumerate(values['x']):
trace = go.Bar(
x=[int(i / 2) for i in x * 2],
y=values['y'][i] * 2,
orientation = 'h',
text=x,
textposition='inside',
hoverinfo = 'none'
)
data.append(trace)
fig = go.Figure(data=data, layout=LAYOUT)
return fig
values = {'x': [[20, 80], [80, 20]],
'y': [['A', 'B'], ['A', 'B']]}
init_notebook_mode()
fig = getStackedSentimentHbarCentered(values)
iplot(fig)
A better approach - use separate annotations.
var x1A = 20;
var x1B = 80;
var x2A = 80;
var x2B = 20;
var trace1 = {
y: ['A', 'B'],
x: [x1A, x1B],
type: 'bar',
orientation: 'h',
};
var trace2 = {
y: ['A', 'B'],
x: [x2A, x2B],
type: 'bar',
orientation: 'h',
};
var data = [trace1, trace2];
var layout = {
barmode: 'stack',
annotations: [
{ x: x1A / 2, y: 'A', text: '20', showarrow: false },
{ x: x1A + x2A / 2, y: 'A', text: '80', showarrow: false },
{ x: x1B / 2, y: 'B', text: '80', showarrow: false },
{ x: x1B + x2B / 2, y: 'B', text: '20', showarrow: false },
],
};
Plotly.newPlot('myDiv', data, layout);
<head>
<!-- Load plotly.js into the DOM -->
<script src='https://cdn.plot.ly/plotly-2.0.0.min.js'></script>
</head>
<body>
<div id='myDiv'><!-- Plotly chart will be drawn inside this DIV --></div>
</body>
Here is an example from the official Plotly documentation: https://plotly.com/python/horizontal-bar-charts/#color-palette-for-bar-chart
As noted in an answer to this question, you can accomplish this much more easily by setting
insidetextanchor="start"
(or 'middle' or 'end')

Categories