I am using heatmap from Plotly. I want to use a logarithmic scale for the color but cannot find how to do so. Here is a MWE:
import plotly.graph_objects as go
import numpy as np
z = [[1e-4,1e-3,1e-2],
[1e-1, 1, 1e1],
[1e2, 1e3, 1e4]]
go.Figure(
data = go.Heatmap(
z = z,
)
).show()
go.Figure(
data = go.Heatmap(
z = np.log(z),
)
).show()
In the MWE I manually calculate the logarithm of the data. I want the color map to be shown as in the second figure but without having to manually transform the data, and also displaying the real z values in the color scale, not the logarithm.
There is an example on the plotly homepage which I adapted to use the viridis colorscale. It's not perfect... you can play with the colorscale denominator to adapt it as you need.
import plotly.graph_objects as go
import plotly.express as px
import numpy as np
viridis = px.colors.sequential.Viridis
z = [[1e-4,1e-3,1e-2],
[1e-1, 1, 1e1],
[1e2, 1e3, 1e4]]
fig1 = go.Figure(
data = go.Heatmap(
z = z,
colorscale = [
[0, viridis[0]],
[1./1000000, viridis[2]],
[1./10000, viridis[4]],
[1./100, viridis[7]],
[1., viridis[9]],
],
colorbar= dict(
tick0= 0,
tickmode= 'array',
tickvals= [0, 1000, 10000]
)
)
)
Another option would be to use:
colorscale = [
[0, viridis[0]],
[1./1000000, viridis[2]],
[1./10000, viridis[4]],
[1./100, viridis[7]],
[1., viridis[9]],
]
px.imshow(z, color_continuous_scale=colorscale, height=600, width=600)
The first one gives you (the second option is rather similar...):
Related
I am using plotly to plot some simple Volumes, like in the code below.
import plotly.graph_objects as go
import numpy as np
X, Y, Z = np.mgrid[-3:3:10j, -5:5:10j, -1:1:3j]
values = np.random.randint(100, size=300)
fig = go.Figure(go.Volume(x=X.flatten(),
y=Y.flatten(),
z=Z.flatten(),
value=values.flatten(),
opacity=1,
surface_count=21))
fig.show()
This results in the following plot.
Is there a way to make the volumes fully intransparent/opaque? I want the boxes to get completly opaque, so I am only seeing the surface of the boxes plotted in the example image and not seeing any internals of the box plotted.
You can use go.Isosurface, if you want to get opaque volume.
import plotly.graph_objects as go
import numpy as np
X, Y, Z = np.mgrid[-3:3:10j, -5:5:10j, -1:1:3j]
values = np.random.randint(100, size=300)
fig = go.Figure(data=[go.Isosurface(
x=X.flatten(),
y=Y.flatten(),
z=Z.flatten(),
value=values.flatten(),
showscale=False,
colorscale='earth',
)])
fig.show()
Output:
I am using Plotly's scatter. I want to have lines surrounding the markers, like in this plot (the black contour):
I want this to happen by default, so I am setting a template like in the below MWE:
import plotly.express as px
import plotly.io as pio
import plotly.graph_objects as go
from plotly.subplots import make_subplots
import numpy as np
MARKERS = ['circle', 'cross', 'x', 'triangle-up', 'star', 'hexagram', 'square', 'diamond', 'hourglass', 'bowtie', 'pentagon', 'triangle-down', 'triangle-left', 'triangle-right', 'star-triangle-up', 'star-triangle-down', 'star-square', 'star-diamond', 'diamond-tall', 'diamond-wide', 'triangle-ne', 'triangle-se', 'triangle-sw', 'triangle-nw', 'hexagon', 'hexagon2', 'octagon']
my_template = pio.templates['plotly']
my_template.data.scatter = [
go.Scatter(
marker = dict(
symbol = s,
line = dict(
width = .5,
),
),
error_y = dict(
width = 1,
thickness = .8
)
) for s in MARKERS
]
pio.templates['my_template'] = my_template
pio.templates.default = 'my_template'
import numpy
import pandas
N_SAMPLES = 99 # Set to 9999 and it fails.
fig = px.scatter(
pandas.DataFrame(
{
'x': numpy.random.randn(N_SAMPLES),
'y': numpy.random.exponential(size=N_SAMPLES),
}
),
x = "x",
y = "y",
)
fig.show()
This works perfectly but if the number of points goes beyond certain value, it stops drawing the lines, like this:
This is what happens to me when I change N_SAMPLES to e.g. 9999. How can I get it to work independently of the number of points?
I have Python 3.8.10 and Plotly 5.11.0.
To cope with the large amount of data, WebGL is available, so I used it to draw a scatterplot with blue markers and a line width of 1. N number is 100,000.
Update:
To set the line width of a marker by default, create a dedicated template and set the line width as its content.
import plotly.graph_objects as go
import numpy as np
my_template = go.layout.Template()
my_template.data.scattergl = [go.Scattergl(marker=dict(line_width=0.5))]
N = 100000
fig = go.Figure()
fig.update_layout(template=my_template)
fig.add_trace(go.Scattergl(
x = np.random.randn(N),
y = np.random.exponential(size=N),
mode='markers',
# marker=dict(
# color='blue',
# line_width=1
# )
))
fig.show()
When I specify a range of y, the graph is not displayed correctly in that range.
I want to display the y-axis in the range of 10f~5u on the log scale, but it doesn't display properly. How can I solve this problem?
# 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=[10 ** -15, 5 * 10 ** -6])
fig.update_layout(
xaxis_type="linear",
yaxis_type="log",
)
fig.show()
In the documentation for log plots, it says that
Setting the range of a logarithmic axis with plotly.graph_objects is very different than setting the range of linear axes: the range is set using the exponent rather than the actual value:
So for your example, you can remove the 10 ** when setting the range, and your range can look like [-15, 1.000011]
The output with this change produces a graph that looks like this:
For reference, the complete code looks like:
# 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=[-15, 1.000011])
fig.update_layout(
xaxis_type="linear",
yaxis_type="log",
)
fig.show()
I have the following lines of code:
import plotly.express as px
fig = px.scatter_matrix(df_fases,
dimensions=["titanite", "amphibole", "epidote", "chlorite","garnet","ilmenite","rutile"], width=1000,
height=1000, title="Rangos de umbral (vmax) por mineral")
fig.update_traces(diagonal_visible=False)
fig.update_traces(marker=dict(size=4))
[enter image description here][1]
fig.show()
... but the x and y axes when I change them with fig.update_xaxes (range = [1.5, 4.5]) and fig.update_yaxes (range = [3, 9]), it only changes some graphics of the scatter matrix plot.How change axis limits in scatter matrix in plotly express for all graphs?
It looks like you have 7 features so you will need to use fig.update_layout and loop through xaxis1... xaxis7 as well as yaxis1... yaxis7. I have hardcoded the number of features for your particular problem, but you can modify this as needed.
fig.update_layout({"xaxis"+str(i+1): dict(range = [1.5, 4.5]) for i in range(7)})
fig.update_layout({"yaxis"+str(i+1): dict(range = [3, 9]) for i in range(7)})
Here is an example of the same thing on the iris data set, where I set the range of each plot:
import plotly.express as px
df = px.data.iris()
fig = px.scatter_matrix(df,
dimensions=["sepal_width", "sepal_length", "petal_width", "petal_length"],
color="species", symbol="species",
title="Scatter matrix of iris data set",
labels={col:col.replace('_', ' ') for col in df.columns}) # remove underscore
fig.update_layout({"xaxis"+str(i+1): dict(range = [0, 10]) for i in range(4)})
fig.update_layout({"yaxis"+str(i+1): dict(range = [0, 10]) for i in range(4)})
fig.update_traces(diagonal_visible=False)
fig.show()
I want to create a lollipop plot with several horizontal line segments like this - https://python-graph-gallery.com/184-lollipop-plot-with-2-group. I'd like to use plotly since I prefer the graphics (and easy interactivity) but can't find a succint way.
There's both line graphs (https://plot.ly/python/line-charts/) and you can add lines in the layout (https://plot.ly/python/shapes/#vertical-and-horizontal-lines-positioned-relative-to-the-axes), but both of these solutions require each line segment to be added separately, with about 4-8 lines of code each. While I could just for-loop this, would appreciate if anyone can point me to anything with inbuilt vectorization, like the matplotlib solution (first link)!
Edit: Also tried the following code, to first make the plot ala matplotlib, then convert to plotly. The line segments disappear in the process. Starting to think it's just impossible.
mpl_fig = plt.figure()
# make matplotlib plot - WITH HLINES
plt.rcParams['figure.figsize'] = [5,5]
ax = mpl_fig.add_subplot(111)
ax.hlines(y=my_range, xmin=ordered_df['value1'], xmax=ordered_df['value2'],
color='grey', alpha=0.4)
ax.scatter(ordered_df['value1'], my_range, color='skyblue', alpha=1,
label='value1')
ax.scatter(ordered_df['value2'], my_range, color='green', alpha=0.4 ,
label='value2')
ax.legend()
# convert to plotly
plotly_fig = tls.mpl_to_plotly(mpl_fig)
plotly_fig['layout']['xaxis1']['showgrid'] = True
plotly_fig['layout']['xaxis1']['autorange'] = True
plotly_fig['layout']['yaxis1']['showgrid'] = True
plotly_fig['layout']['yaxis1']['autorange'] = True
# plot: hlines disappear :/
iplot(plotly_fig)
You can use None in the data like this:
import plotly.offline as pyo
import plotly.graph_objs as go
fig = go.Figure()
x = [1, 4, None, 2, 3, None, 3, 4]
y = [0, 0, None, 1, 1, None, 2, 2]
fig.add_trace(
go.Scatter(x=x, y=y))
pyo.plot(fig)
Plotly doesn't provide a built in vectorization for such chart, because it can be done easily by yourself, see my example based on your provided links:
import pandas as pd
import numpy as np
import plotly.offline as pyo
import plotly.graph_objs as go
# Create a dataframe
value1 = np.random.uniform(size = 20)
value2 = value1 + np.random.uniform(size = 20) / 4
df = pd.DataFrame({'group':list(map(chr, range(65, 85))), 'value1':value1 , 'value2':value2 })
my_range=range(1,len(df.index)+1)
# Add title and axis names
data1 = go.Scatter(
x=df['value1'],
y=np.array(my_range),
mode='markers',
marker=dict(color='blue')
)
data2 = go.Scatter(
x=df['value2'],
y=np.array(my_range),
mode='markers',
marker=dict(color='green')
)
# Horizontal line shape
shapes=[dict(
type='line',
x0 = df['value1'].loc[i],
y0 = i + 1,
x1 = df['value2'].loc[i],
y1 = i + 1,
line = dict(
color = 'grey',
width = 2
)
) for i in range(len(df['value1']))]
layout = go.Layout(
shapes = shapes,
title='Lollipop Chart'
)
# Plot the chart
fig = go.Figure([data1, data2], layout)
pyo.plot(fig)
With the result I got: