I have the following code to create the line plot with Plotly. How can I set the range of Y axis to always have it in [0; 10]?
layout = go.Layout(
title=go.layout.Title(
text="Test",
xref='paper',
x=0
),
xaxis=go.layout.XAxis(
tickmode='linear',
tickfont=dict(
size=10
),
title=go.layout.xaxis.Title(
font=dict(
size=14,
color='#7f7f7f'
)
)
),
yaxis=go.layout.YAxis(
title=go.layout.yaxis.Title(
text=y,
font=dict(
size=14,
color='#7f7f7f'
)
)
)
)
data = [go.Scatter(x=x1, y=y1)]
Update for newer versions
When setting up a figure you can use plotly's magic underscore notation and specify layout_yaxis_range=[<from_value>, <to_value>] like this:
fig = go.Figure(data=go.Scatter(x=x, y=y, mode='lines'), layout_yaxis_range=[-4,4])
Or if you've already got a figure named fig, you can use:
fig.update_layout(yaxis_range=[-4,4])
And:
fig.update(layout_yaxis_range = [-4,4])
Or:
fig.update_yaxes(range = [-4,4])
Figure:
Complete code:
# imports
import pandas as pd
import plotly.graph_objs as go
import numpy as np
# data
np.random.seed(4)
x = np.linspace(0, 1, 50)
y = np.cumsum(np.random.randn(50))
# plotly line chart
fig = go.Figure(data=go.Scatter(x=x, y=y, mode='lines'), layout_yaxis_range=[-4,4])
fig.update_layout(yaxis_range=[-4,4])
fig.show()
Original answer using plotly.offline, iplot and no magic underscore notation:
When setting up a figure, use:
layout = go.Layout(yaxis=dict(range=[fromValue, toValue])
Or if you've already got a figure named fig, you can use:
fig.update_layout(yaxis=dict(range=[fromValue,toValue]))
Plot:
Complete code for Jupyter Notebook:
# imports
from plotly.offline import download_plotlyjs, init_notebook_mode, plot, iplot
import pandas as pd
import plotly.graph_objs as go
import numpy as np
# setup
init_notebook_mode(connected=True)
# data
np.random.seed(4)
x = np.linspace(0, 1, 50)
y = np.cumsum(np.random.randn(50))
# line
trace = go.Scatter(
x=x,
y=y,
)
# layout
layout = go.Layout(yaxis=dict(range=[-4,4])
)
# Plot
fig = go.Figure(data=[trace], layout=layout)
iplot(fig)
Some important details:
With this setup, you can easily add an y axis title like this:
# layout
layout = go.Layout(yaxis=dict(range=[-4,4]), title='y Axis')
)
It's a little more tricky if you'd like to format that title further. I find it easiest to actually add another element with title = go.layout.yaxis.Title(text='y Axis', font=dict(size=14, color='#7f7f7f'). As long as you do it the right way, you should not experience the situation in your comment above:
Thanks. I tried it. But then I have 2 definitions of yaxis in the
Layout: yaxis=dict(range=[0, 10]) and yaxis=go.layout.YAxis. Therefore
an error appears.
Take a look at this:
Plot:
Complete code with y-axis text formatting:
# imports
from plotly.offline import download_plotlyjs, init_notebook_mode, plot, iplot
import pandas as pd
import plotly.graph_objs as go
import numpy as np
# setup
init_notebook_mode(connected=True)
# data
np.random.seed(4)
x = np.linspace(0, 1, 50)
y = np.cumsum(np.random.randn(50))
# line
trace = go.Scatter(
x=x,
y=y,
)
# layout
layout = go.Layout(
yaxis=dict(range=[-4,4],
title = go.layout.yaxis.Title(text='y Axis', font=dict(size=14, color='#7f7f7f')))
)
# Plot
fig = go.Figure(data=[trace], layout=layout)
iplot(fig)
If I understand you right you want to limit the range of the y-axis itself. You can pass a dict in the keyword argument yaxis. It could be something like go.Layout(yaxis=dict(range=[0, 10])) I hope this helps you.
Related
I would like to have a multiple line plot within same canvas tied with the same x-axis as shown something in the figure:
Using subplots does not achieve the intended desire.
import plotly.express as px
from plotly.subplots import make_subplots
import plotly.graph_objects as go
fig = make_subplots(rows=2, shared_xaxes=True,vertical_spacing=0.1)
fig.add_scatter(y=[2, 1, 3], row=1, col=1)
fig.add_scatter(y=[1, 3, 2], row=2, col=1)
fig.show()
May I know how this can be done, appreciate if someone can point to good reading material
With a dataset such as this you can select any number of columns, set up a figure using fig = make_subplots() with shared_xaxes set to True and then add your series with a shared x-axis using fig.add_trace(go.Scatter(x=df[col].index, y=df[col].values), row=i, col=1) in a loop to get this:
Let me know if this is a setup you can use but need a little tweaking.
Complete code:
import plotly.graph_objects as go
import plotly.io as pio
from plotly.subplots import make_subplots
import pandas as pd
# data
pio.templates.default = "plotly_white"
df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/finance-charts-apple.csv')
df = df.set_index('Date')
df.tail()
cols = df.columns[:-4]
ncols = len(cols)
# subplot setup
fig = make_subplots(rows=ncols, cols=1, shared_xaxes=True)
for i, col in enumerate(cols, start=1):
fig.add_trace(go.Scatter(x=df[col].index, y=df[col].values), row=i, col=1)
fig.show()
Depending on the data you are plotting, I think you could either check out "Stacked Subplots with a Shared X-Axis (low-level API)" on https://plotly.com/python/subplots/
Or separate the data by shifting each line plot upwards like so:
import plotly.graph_objects as go
import random
data = []
n = 9
for x in range(10, 60, 10):
points = [value + x for value in random.sample(range(1,n+1), k = n)]
data.append(go.Scatter(y=points))
fig = go.Figure(data = data)
fig.show()
I have some old code that graphs lots of lines on the same graph in a manner like
import plotly.plotly as py
import plotly.graph_objs as go
data = [regtimes, avg5times]
py.iplot(data, filename='basic-line')
and this would graph both lines on the same plot. I tried to use this again and it says plotly.plotly is deprecated. Now I have something like
individualtimes = go.Scatter(
y = times,
x = x1,
)
test = go.Scatter(
y2=[1, 1, 5],
x2=x1
)
data = [individualtimes,test]
fig = go.Figure(data=data)
fig.show()
Is there a way to use fig.show to graph multiple lines like this? Thanks!
I have found the answer! It has been changes to use add_trace and then show the figure. Plotly uses
import plotly.graph_objects as go
# Create random data with numpy
import numpy as np
np.random.seed(1)
N = 100
random_x = np.linspace(0, 1, N)
random_y0 = np.random.randn(N) + 5
random_y1 = np.random.randn(N)
random_y2 = np.random.randn(N) - 5
# Create traces
fig = go.Figure()
fig.add_trace(go.Scatter(x=random_x, y=random_y0,
mode='lines',
name='lines'))
fig.add_trace(go.Scatter(x=random_x, y=random_y1,
mode='lines+markers',
name='lines+markers'))
fig.add_trace(go.Scatter(x=random_x, y=random_y2,
mode='markers', name='markers'))
fig.show()
The rest of this can be found here.
I have a 3d plot working with z_axis asymmetrical error bars, but when I hover over the data points, I'm only getting the (x,y,z) information instead of (x,y,z +err/-err).
Plotly documentation for the error bars indicates that this information should be automatically included in the hover label. I tried using the hovertext attribute (setting hoverinfo='text' per the Scatter3d docs) with no success. Perhaps my attempt at reformatting labels isn't in the format that plotly requires, but I've tried a few different ways now to no avail. Below is the code trying to use the hovertext and hoverinfo attributes.
import pandas as pd
import numpy as np
import plotly.plotly as py
import plotly.graph_objs as go
from plotly.offline import iplot, init_notebook_mode
import cufflinks as cf
cf.go_offline()
cf.set_config_file(world_readable=True,theme='pearl',offline=True)
init_notebook_mode()
x = [1,2,3,4,5]
y = [1,2,3,4,5]
z1 = [1,2,3,4,5]
z2 = np.multiply(z1,2)
z3 = np.multiply(z1,0.5)
df = pd.DataFrame({'A':x,'B':y,'C':z1,'D':z2,'E':z3})
test = []
for row in df.values:
test.append('x:{}; y:{}; z={} +{}/-{}'.format(row[0],row[1],row[2],row[3],row[4]))
fig = go.Figure()
fig.add_trace(
go.Scatter3d(
x=x,
y=y,
z=z1,
# https://plot.ly/python/reference/#scatter3d-error_z
error_z = dict(
visible=True,
type='data',
array=np.subtract(z2,z1),
arrayminus=np.subtract(z1,z3)
),
name='Test Plot',
marker=dict(size=4),
opacity = 1, # 1=default
mode='markers',
hovertext=test,
hoverinfo='text' # set this to 'text' if using 'hovertext' attr
)
)
fig.layout.update(scene = dict(
xaxis_title='X Axis',
yaxis_title='Y Axis',
zaxis_title='Output')
)
fig.show()
I have a plotly bar chart, from a dataframe:
fig = df.iplot(asFigure=True, kind='bar', barmode = 'relative')
py.iplot(fig)
Is it possible to turn one of the columns in the data frame into a line series?
The suggested link in the comments does have some valuable resources, but they won't answer your questions directly. iplot() uses a pandas dataframe as input, and produces a stacked barplot. Here's an approach that will let you do exactly that, albeit without using df.iplot()
First, the plot :
Now, the code
My suggestion builds on an example found at: plot.ly/pandas/bar-charts. As you'll see that's an example that builds on a pandas dataframe - just like df.iplot(). You can simply take a series or 'trace' out of the stacked bars and display it as a line by changing
go.Bar(x=df['x'],
y=df['y4'])
to:
go.Scatter(x=df['x'],
y=df['y4'])
I've also added a few elements to make it easier to display your results offline in a Jupyter notebook. Also note that I've changed the last line from py.iplot(fig, filename='pandas-bar-chart-layout') to just iplot(fig, filename='pandas-bar-chart-layout')
Complete snippet:
import plotly.plotly as py
import plotly.graph_objs as go
from plotly.offline import download_plotlyjs, init_notebook_mode, plot, iplot
init_notebook_mode(connected=True)
import pandas as pd
import numpy as np
N = 20
x = np.linspace(1, 10, N)
y = np.random.randn(N)+3
y2 = np.random.randn(N)+6
y3 = np.random.randn(N)+9
y4 = np.random.randn(N)+12
df = pd.DataFrame({'x': x, 'y': y, 'y2':y2, 'y3':y3, 'y4':y4})
df.head()
data = [
go.Bar(
x=df['x'], # assign x as the dataframe column 'x'
y=df['y']
),
go.Bar(
x=df['x'],
y=df['y2']
),
go.Bar(
x=df['x'],
y=df['y3']
),
go.Scatter(
x=df['x'],
y=df['y4']
)
]
layout = go.Layout(
barmode='stack',
title='Stacked Bar with Pandas'
)
fig = go.Figure(data=data, layout=layout)
# IPython notebook
iplot(fig, filename='pandas-bar-chart-layout')
answering to the last comment, I changed the code to include a loop like you asked.
Let me know if this helps:
import plotly.plotly as py
import plotly.graph_objs as go
from plotly.offline import download_plotlyjs, init_notebook_mode, plot, iplot
init_notebook_mode(connected=True)
import pandas as pd
import numpy as np
N = 20
x = np.linspace(1, 10, N)
y = np.random.randn(N)+3
y2 = np.random.randn(N)+6
y3 = np.random.randn(N)+9
y4 = np.random.randn(N)+12
df = pd.DataFrame({'x': x, 'y': y, 'y2':y2, 'y3':y3, 'y4':y4})
df.head()
data = []
for i in df.columns:
if i!= "x":
data.append(
go.Bar(
x=df['x'], # assign x as the dataframe column 'x'
y=df[i]
)
)
layout = go.Layout(
barmode='stack',
title='Stacked Bar with Pandas'
)
fig = go.Figure(data=data, layout=layout)
# IPython notebook
iplot(fig, filename='pandas-bar-chart-layout')
I am trying to plot a cumulative histogram using Plotly in python, but make it look like "steps", i.e. bars with no color and only the top line is displayed. Something like this:
Basically, I'm trying to reproduce the behavior of the following matplotlib code:
import matplotlib.pyplot as plt
plt.hist(x, cumulative=True, histtype='step')
So far, the best I've been able to do is:
import plotly.graph_objs as go
from plotly.offline import iplot
h = go.Histogram(x=x,
cumulative=dict(enabled=True),
marker=dict(color="rgba(0,0,0,0)",
line=dict(color="red", width=1)))
iplot([h])
Which results in something like:
So what's the trick?
If you're willing to handle the binning and accumulation before you plot the data, you can use a go.Scatter object with the shape property of the line set to 'hvh'.
Plot:
Code: Setup for a Jupyter Notebook
#imports
import plotly.plotly as py
import plotly.graph_objs as go
from plotly.offline import download_plotlyjs, init_notebook_mode, plot, iplot
import numpy as np
import pandas as pd
# qtconsole for debugging
#%qtconsole -- style vim
# Notebook settings
init_notebook_mode(connected=True)
# Some sample data
x = np.random.normal(50, 5, 500)
binned = np.histogram(x, bins=25, density=True)
plot_y = np.cumsum(binned[0])
# Line
trace1 = go.Scatter(
x=binned[1],
y=plot_y,
mode='lines',
name="X",
hoverinfo='all',
line=dict(color = 'rgb(1255, 0, 0)', shape='hvh'
)
)
data = [trace1]
# Layout
layout = dict(title = 'Binned data from normal distribution',
legend=dict(
y=0.5,
traceorder='reversed',
font=dict(
size=16
)
)
)
# Make figure
fig = dict(data=data, layout=layout)
# Plot
iplot(fig, filename='line-shapes')
I hope this is something you can use!
Don't hesitate to let me know if not.
Some details:
The data sample is made using np.random.normal(). x is a sampled normal distribution with mean = 50, sigma = 5 and 500 observations. x is then put in 50 bins using np.histogram() which returns two arrays. These are used as data source for the plot.
Possible alternative approaches:
I also tried using your snippet with some random sample data and include shape='hvh' in your line=dict(color="red", width=1). That did not seem to work though. I also considered modifying the layout of your go.Histogram() so that only the top line of the bars were plotted, but I don't think it's possible.
The accepted solution works but may be limiting as the bins are all of equal width. One approach is to use matplotlib to calculate stats, then plot with plotly:
# sample data
# I am not using a normal distribution on purpose so that the effect of varying bin widths is apparent.
x = np.random.rand(100)
# use matplotlib to get "n" and "bins"
# n_bins will affect the resolution of the cumilative histogram but not dictate the bin widths.
n_bins = 100
n, bins, patches = plt.hist(x, n_bins, density=True, histtype='step', cumulative=-1)
# use plotly (v3) to plot
data = []
trace = go.Scatter(
x=bins,
y=n,
mode='lines',
name= "test",
line=dict(
shape='hvh'
)
)
data.append(trace)
fig = go.Figure(data=data)
iplot(fig)
The result should look something like this: