Related
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)
I am trying to showcase a scatter plot as well as the data for the the plot side by side in jupyter. I wish to add a plotly button (dropdown) that will show the filtered data as well as the corresponding scatter plot. Is this possible WITHOUT USING ipywidgets, using plotly dropdowns?
I was able to build two separate plots for data and scatter plot with dropdowns but cannot combine them together. Following is the code I tried. Here the dropdown only interacts with the table, the scatter plot is not updating.
import plotly.express as px
import plotly.graph_objects as go
import numpy as np
import pandas as pd
df = px.data.iris()
species = sorted(set(df['species']))
#fig=go.Figure()
default_species = "setosa"
df_default = df[df['species']==default_species]
fig = make_subplots(
rows=1, cols=2,
shared_xaxes=True,
horizontal_spacing=0.02,
specs=[[{"type": "scatter"},{"type": "table"}]]
)
fig.add_trace(
go.Scatter(
x=df_default["sepal_length"],
y=df_default["sepal_width"],
mode="markers"
),
row=1, col=1
)
fig.add_trace(
go.Table(
header=dict(
values=["sepal<br>length","sepal<br>length","petal<br>length","petal<br>width","species","species<br>id"],
font=dict(size=10),
align="left"
),
cells=dict(
values=[df_default[k].tolist() for k in df_default.columns],
align = "left")
),
row=1, col=2
)
buttons = []
for s in species:
s_data = df[df['species']==s]
buttons.append(dict(
method='restyle',
label=s,
visible=True,
args=[
{'values':[["sepal<br>length","sepal<br>length","petal<br>length","petal<br>width","species","species<br>id"]],
'cells':[dict(values=[s_data[k].tolist() for k in s_data.columns],align = "left")]},
{'y':[s_data["sepal_width"]],
'x':[s_data['sepal_length']],
'type':'scatter',
'mode':'markers'}
]
))
#fig.update_layout(width=1500, height=500)
# some adjustments to the updatemenus
updatemenu = []
your_menu = dict()
updatemenu.append(your_menu)
updatemenu[0]['buttons'] = buttons
updatemenu[0]['direction'] = 'down'
updatemenu[0]['showactive'] = True
updatemenu[0]['active'] = species.index(default_species)
updatemenu[0]['x'] = 0
updatemenu[0]['xanchor'] = 'left'
updatemenu[0]['y'] = 1.2
updatemenu[0]['yanchor'] = 'top'
# add dropdown menus to the figure
fig.update_layout(showlegend=False,
updatemenus=updatemenu,
xaxis_title="Sepal_Length",
yaxis_title="Sepal_Width"
)
fig.show()
I do not want to use ipywidgets.
The code that worked for me: Editing hope it helps some one
## Create Combination of Scatter Plot and Plotly Tables with interactive Static HTML
import plotly.express as px
import plotly.graph_objects as go
from plotly.subplots import make_subplots
import numpy as np
import pandas as pd
df = px.data.iris()
species_list = sorted(set(df['species']))
# --- function ---
def make_multi_plot(df1, item_list):
fig = make_subplots(rows=1,
cols=2,
#shared_xaxes=True,
#vertical_spacing=0.2,
specs = [[{}, {"type": "table"}]]
)
for item_id in item_list:
#print('item_id:', item_id)
trace1 = go.Scatter(
x=df1.loc[df1.species.isin([item_id])].sepal_length,
y=df1.loc[df1.species.isin([item_id])].sepal_width,
mode='markers',
name = str(item_id)
)
fig.append_trace(trace1, 1, 1)
trace2 = go.Table(
columnorder = [1,2,3,4,5,6],
columnwidth = [2,2,2,2,4,2],
header=dict(
values = ["sepal<br>length","sepal<br>length","petal<br>length","petal<br>width","species","species<br>id"],
font = dict(size=10),
align = "left"
),
cells = dict(
values = [df1[df1.species.isin([item_id])][k].tolist() for k in df1[df1.species.isin([item_id])].columns[:]],
align = "left"
)
)
fig.append_trace(trace2,1,2)
Ld = len(fig.data)
#print(Ld)
Lc = len(item_list)
for k in range(2, Ld):
fig.update_traces(visible=False, selector=k)
def create_layout_button(k, item_id):
#print(k, item_id)
visibility = [False]*2*Lc
for tr in [2*k, 2*k+1]:
visibility[tr] = True
#print(visibility)
return dict(label = item_id,
method = 'restyle',
args = [{'visible': visibility,
'title': item_id
}])
#updatemenu[0]['x'] = 0
#updatemenu[0]['xanchor'] = 'left'
#updatemenu[0]['y'] = 1.2
#updatemenu[0]['yanchor'] = 'top'
fig.update_layout(
updatemenus=[go.layout.Updatemenu(
active=0,
buttons=[create_layout_button(k, item_id) for k, item_id in enumerate(item_list)],
x=0.5,
y=1.3
)],
#title='Model Raporu',
#template='plotly_dark',
#height=800
xaxis_title="Sepal_Length",
yaxis_title="Sepal_Width"
)
fig.show()
# --- main ---
make_multi_plot(df1=df, item_list=species_list)
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()
I'm trying to make an animated scatter plot over fixed surface using plotly.
This is a code I use to draw the surface:
import plotly.graph_objects as go
def surface(x, y, z, opacity: float = 1.0) -> go.Figure:
fig = go.Figure()
fig.add_trace(
go.Surface(
x=x,
y=y,
z=z,
contours_z=dict(
show=True,
usecolormap=True,
project_z=True,
),
opacity=opacity
)
)
return fig
Then I'm trying to overlay scatter plots over it.
def population(
self,
benchmark: CEC2013,
batch_stats: BatchStats,
filename: str = 'population'
):
# Here I'm creating the surface figure using previous method
surface = figure.surface.surface(*benchmark.surface, opacity=0.8)
frames = []
# Time to add some frames using Scatter 3D
for population in batch_stats.population_history:
x = [solution.genome[0] for solution in population.solutions]
y = [solution.genome[1] for solution in population.solutions]
fitness = population.fitness
frame = go.Frame(
data=[
go.Scatter3d(
x=x,
y=y,
z=fitness,
mode='markers',
marker=dict(
size=6,
color='#52CA34',
)
)
]
)
frames.append(frame)
# Update frames to root figure
surface.frames = frames
# just a fancy display, to make it work in offline mode in html render from notebook
pyo.iplot(
surface,
filename=filename,
image_width=self.IMAGE_WIDTH,
image_height=self.IMAGE_HEIGHT
)
Surface displays only in a first frame. Scatter plots are displayed in subsequent frames, but without underlaying surface.
Code is located here on a dev branch. There's debug notebook named test_vis.ipynb at the root. Thanks for help <3
I've posted this question as an issue at plotly's repository.
Here's an answer I've received.
#empet - thank you <3
When your fig.data contains only one trace then it is supposed that each frame updates that trace
and the trace is no more displayed during the animation.
That's why you must define:
fig = go.Figure(
data=[
go.Scatter(
y=y,
x=x,
mode="lines",
ine_shape='spline'
)
]*2
)
i.e. include the same trace twice in fig.data.
At the same time modify the frame definition as follows:
frame = go.Frame(data=[scatter], traces=[1])
traces = [1] informs plotly.js that each frame updates the trace fig.data[1], while fig.data[0] is unchanged during the animation.
Here's a complete example of how to make an animation over some based plot.
import math
import numpy as np
import plotly.graph_objects as go
import plotly.io as pio
import plotly.offline as pyo
class Plot:
def __init__(
self,
image_width: int = 1200,
image_height: int = 900
) -> None:
self.IMAGE_WIDTH = image_width
self.IMAGE_HEIGHT = image_height
pyo.init_notebook_mode(connected=False)
pio.renderers.default = 'notebook'
def population(self, filename: str = 'population'):
x_spline = np.linspace(
start=0,
stop=20,
num=100,
endpoint=True
)
y_spline = np.array([math.sin(x_i) for x_i in x_spline])
x_min = np.min(x_spline)
x_max = np.max(x_spline)
y_min = np.min(y_spline)
y_max = np.max(y_spline)
spline = go.Scatter(
y=y_spline,
x=x_spline,
mode="lines",
line_shape='spline'
)
fig = go.Figure(
data=[spline] * 2
)
frames = []
for i in range(50):
x = np.random.random_sample(size=5)
x *= x_max
y = np.array([math.sin(x_i) for x_i in x])
scatter = go.Scatter(
x=x,
y=y,
mode='markers',
marker=dict(
color='Green',
size=12,
line=dict(
color='Red',
width=2
)
),
)
frame = go.Frame(data=[scatter], traces=[1])
frames.append(frame)
fig.frames = frames
fig.layout = go.Layout(
xaxis=dict(
range=[x_min, x_max],
autorange=False
),
yaxis=dict(
range=[y_min, y_max],
autorange=False
),
title="Start Title",
updatemenus=[
dict(
type="buttons",
buttons=[
dict(
label="Play",
method="animate",
args=[None]
)
]
)
]
)
fig.update_layout(
xaxis_title='x',
yaxis_title='y',
title='Fitness landscape',
# autosize=True
)
pyo.iplot(
fig,
filename=filename,
image_width=self.IMAGE_WIDTH,
image_height=self.IMAGE_HEIGHT
)
plot = Plot()
plot.population()
I want to add a (horizontal) scrollbar to the X axis, because the number of points is large. How can I do it?
trace0 = go.Scatter(
x = x1_values,
y = y1_values,
name = "V1"
)
data = [trace0]
layout = dict(title = title,
xaxis = dict(tickmode='linear', tickfont=dict(size=10)),
yaxis = dict(title = "Title")
)
fig = dict(data=data, layout=layout)
iplot(fig)
Using plotly you can add a rangeslider using fig['layout']['xaxis']['rangeslider'] with functionality that exceeds that of a scrollbar:
Plot:
Code:
Here's an example using some random data in an off-line Jupyter Notebook.
# imports
from plotly.offline import download_plotlyjs, init_notebook_mode, plot, iplot
from IPython.core.display import display, HTML
import plotly.figure_factory as ff
import plotly.graph_objs as go
import pandas as pd
import numpy as np
# setup
display(HTML("<style>.container { width:35% !important; } .widget-select > select {background-color: gainsboro;}</style>"))
init_notebook_mode(connected=True)
np.random.seed(1)
# random time series sample
df = pd.Series(np.random.randn(1000),index=pd.date_range('1/1/2000', periods=1000)).cumsum().to_frame()+100
df.columns = ['Series1']
# trace / line
trace1 = go.Scatter(
x=df.index,
y=df['Series1'],
name = "AAPL High",
line = dict(color = 'blue'),
opacity = 0.4)
# plot layout
layout = dict(
title='Slider / Scrollbar',
xaxis=dict(
rangeselector=dict(
buttons=list([
dict(count=1,
label='1m',
step='month',
stepmode='backward'),
dict(count=6,
label='6m',
step='month',
stepmode='backward'),
dict(step='all')
])
),
rangeslider=dict(
visible = True
),
type='date'
)
)
# plot figure
data = [trace1]
fig = dict(data=data, layout=layout)
iplot(fig)
For more details take a look here.