Plotly: How to plot a cumulative "steps" histogram? - python

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:

Related

I want to specify a color in plotly [duplicate]

This question already has an answer here:
Plotly: How to define colors in a figure using Plotly Graph Objects and Plotly Express?
(1 answer)
Closed 1 year ago.
I want to use plotly to specify the color.
However, with the current code, using marker=dict(color=colors) will naturally result in an error.
How can I specify the type and also the color at the same time?
import plotly.express as px
fig = px.scatter(
df,
x=x_axis,
y=y_axis,
color="species",
)
fig.show()
As an image, I want to specify something like this. color is a list, and it contains the same kind of data as species.
import seaborn as sns
def get_colorpalette(colorpalette, file_number):
palette = sns.color_palette(
colorpalette, file_number)
rgb = ['rgb({},{},{},{})'.format(*[x*256 for x in rgb],1)
for rgb in palette]
return rgb
colors = get_colorpalette('hls', graphNumber)
fig = px.scatter(
df,
x=x_axis,
y=y_axis,
color="species",
marker=dict(color=colors)
)
fig.show()
postscript
I have prepared color in RGB, but it would be nice if I could specify the color in RGB in plotly.
The following is an example of how to specify a color in plotly.
import numpy as np
import seaborn as sns
import plotly.graph_objs as go
import plotly.offline as py
import plotly
def get_colorpalette(colorpalette, n_colors):
palette = sns.color_palette(
colorpalette, n_colors)
rgb = ['rgb({},{},{})'.format(*[x*256 for x in rgb])
for rgb in palette]
return rgb
n_legends = 12
x = np.arange(0, 1, .01)
y = np.random.rand(n_legends, 100) + \
np.arange(n_legends).reshape(-1, 1)
colors = get_colorpalette('hls', n_legends)
data = [
go.Scatter(
x=x, y=y[i], name='凡例 {:02d}'.format(i),
marker={'color':colors[i]})
for i in range(n_legends)]
fig = go.Figure(data=data)
py.iplot(fig)
Arbitrary color settings can be made with the following settings See this page for details. The following code was taken from the sample in the official reference.
import plotly.express as px
df = px.data.iris()
fig = px.scatter(df,
x="sepal_width",
y="sepal_length",
color="species",
size='petal_length',
hover_data=['petal_width'],
color_discrete_sequence=["blue", "goldenrod", "magenta"])
fig.show()
By default, Plotly Express will use the color sequence from the active template's layout. colorway attribute, and the default active template is plotly which uses the plotly color sequence. You can choose any of the following built-in qualitative color sequences from the px. colors.

Matplotlib graphics problems in python

I have the following graphic generated with the following code
I want to correct the x-axis display to make the date more readable.
I would also like to be able to enlarge the graph
My code is :
import requests
import urllib.parse
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
def get_api_call(ids, **kwargs):
API_BASE_URL = "https://apis.datos.gob.ar/series/api/"
kwargs["ids"] = ",".join(ids)
return "{}{}?{}".format(API_BASE_URL, "series", urllib.parse.urlencode(kwargs))
df = pd.read_csv(get_api_call(
["168.1_T_CAMBIOR_D_0_0_26", "101.1_I2NG_2016_M_22",
"116.3_TCRMA_0_M_36", "143.3_NO_PR_2004_A_21", "11.3_VMATC_2004_M_12"],
format="csv", start_date=2018
))
time = df.indice_tiempo
construccion=df.construccion
emae = df.emae_original
time = pd.to_datetime(time)
list = d = {'date':time,'const':construccion,'EMAE':emae}
dataset = pd.DataFrame(list)
plt.plot( 'date', 'EMAE', data=dataset, marker='o', markerfacecolor='blue', markersize=12, color='skyblue', linewidth=4)
plt.plot( 'date', 'const', data=dataset, marker='', color='olive', linewidth=2)
plt.legend()
To make the x-tick labels more readable, try rotating them. So use, for example, a 90 degree rotation.
plt.xticks(rotation=90)
To enlarge the size, you can define your own size using the following in the beginning for instance
fig, ax = plt.subplots(figsize=(10, 8))
I am fairly sure that this can be done by using the window itself of Matplotlib. If you have the latest version you can enlarge on a section of the graph by clicking the zoom button in the bottom left. To get the x-tick labels to be more readable you can simply click the expand button in the top right or use Sheldore's solution.

Scatter 3d in Plotly Express - Colab Notebook is not plotting with equal axes

Trying to plot a very simple 3d scatter plot with x,y,z axes all equal in length. It is not working.
Code:
'''
from mpl_toolkits import mplot3d
import pandas
from pandas import DataFrame
pt_num = 100
x = np.random.uniform(-10,10,size=(pt_num,2))
model = np.array([2,2]).reshape(-1,1)
y = np.dot(x,model)
data = np.hstack((x,y))
dats = {'x':data[:,0].squeeze(),'w':data[:,1].squeeze(),'y':data[:,2].squeeze()}
df = DataFrame(data=dats)
import plotly.express as px
fig = px.scatter_3d(df, x='x', y='w', z='y',width=1200, height=1200)
fig.update_layout(scene=dict(xaxis=dict(range=[-10,10]),yaxis=dict(range=[-10,10]),zaxis=dict(range=[-10,10])))
fig['layout'].update(width=1500, height=1500, autosize=False)
fig.show()
'''
Thank you for any help.
Asked too soon out of frustration. The answer is to add 'aspectmode="cube"' to the scene dict for fig.update_layout:
fig.update_layout(scene=dict(xaxis=dict(range=view_range),yaxis=dict(range=view_range),zaxis=dict(range=view_range),aspectmode="cube"))

How to Change x-axis to logarithmic in PLOTLY histogram

How to make x-axis of the following histogram, logarithmic?
The following code:
data_list = [1,1,5,5,5,100,100]
import plotly.graph_objects as go
fig = go.Figure()
fig.add_trace(go.Histogram(x=data_list, nbinsx=100))
import plotly.offline as py
py.init_notebook_mode(connected=False)
py.offline.plot(fig, filename = 'test.html')
Produces typical histogram.
How can I change the x-axis logarithmic?
I also tried:
data_list = [1,1,5,5,5,100,100]
import plotly.graph_objects as go
fig = go.Figure()
fig.add_trace(go.Histogram(x=data_list, nbinsx=100))
fig.update_layout(xaxis_type="log")
fig.update_xaxes(tick0=0, dtick=1, range=[0,2.5])
import plotly.offline as py
py.init_notebook_mode(connected=False)
py.offline.plot(fig, filename = 'test.html')
but this will result in non-logarithmic bins, and essentially, the bin at 100 disappears!
As said above in the comments, logarithmic axes are not possible with plotly. You could try to create bins using numpy and create a bar plot with those.

Plotly: How to set the range of the y axis?

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.

Categories