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()
Related
Here is the graph I have:
...and here is the graph I want, without the decimal places:
...and here is the code I have for the graph:
import plotly.express as px
from pandas import DataFrame
# The data
data = {"r": [3, 2, 3, 2, 2, 2],
"theta": ['Python', 'Java', 'VBA', 'C#', 'C++', 'C']}
# Convert to DF
df = DataFrame(data)
fig = px.line_polar(df, r='r', theta='theta', line_close=True, markers=True, range_r=(0,3))
fig.update_traces(fill='toself')
# Update the font of the graph
fig.update_layout(
font=dict(
family="Calibri",
size=24, # Set the font size here
color="Black",
)
)
# Display the graph and save it
# fig.write_html("graphs/programming_languages.html")
fig.show()
To set an arbitrary scale, specify the scale value in a list in the layout settings. Alternatively, you can specify the scale interval. In this case, the interval value is 1.
fig.layout.polar.radialaxis.tickvals = [0,1,2,3]
#fig.layout.polar.radialaxis.dtick = 1
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...):
I created a Plotly windrose and wanted to change the inner circle limits to some other values(to get the same circle limit as my other wind roses). Here I want to change inner circle size to 0,2,4,6,8,10 to 0,2.5,5,7.5,10. Here is my code and my current windrose is already attached.
import plotly.express as px
df = px.data.wind()
fig = px.bar_polar(df, r="frequency", theta="direction",
color="strength", template="plotly_dark",
color_discrete_sequence=px.colors.sequential.Plasma_r)
fig.show()
This is not well documented but it has a similar behaviour of tickmode--array.
import plotly.express as px
df = px.data.wind()
fig = px.bar_polar(df, r="frequency", theta="direction",
color="strength", template="plotly_dark",
color_discrete_sequence= px.colors.sequential.Plasma_r)
fig.update_layout(
polar=dict(
radialaxis=dict(tickvals = [0, 2.5, 5, 7.5, 10])
)
)
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:
Are there guidelines on how to set up secondary Y-axes in python for plotly?
I am assinging axis style through an iterative loop, as follows:
all_plots = ['plot1','plot2'...'plot20']
fig = tools.make_subplots(rows=nrow, cols=ncol, shared_xaxes=False, shared_yaxes=False, subplot_titles=all_plots)
for i in all_plots:
fig['layout']['yaxis'+str(j)].update()
How does the assignment of y axes work?
If my subplot included, say, 4 rows and 5 columns for a total of 20 subplots, do I have to assume that plotly needs to receive odd and even numbers, meaning:
yaxis1 and yaxis2 for plot1
....
yaxis39 and yaxis40 for plot20
It is possible, to do this, but its not particularly intuitive. Take this example where I create a plot 2x2 subplots, and add a secondary y axis to the plot in position 2,2.
When you create a subplots, they are assigned y axes: "y1","y2","y3","y4" on the left side of each subplot. To a secondary y axes, you need to use fig['layout'].updateto create new axes "y5", "y6", "y7", "y8" which correspond to "y1","y2","y3","y4". So the bottom right subplot would have axes y4(right) and y8(left). In the example below, I only create a secondary y axis for the last plot, but expanding it to more/all the subplots is pretty straightforward.
It is important to note, that creating the secondary axes, and assigning it in trace5 doesn't automatically place it on the proper axes. You still have to manually assign it with fig['data'][4].update(yaxis='y'+str(8)) to plot it relative to the left axis.
fig = tools.make_subplots(rows=2, cols=2,subplot_titles=('Air Temperature', 'Photon Flux Density',
'Ground Temps','Water Table & Precip'))
fig['layout']['xaxis1'].update( range=[174, 256])
fig['layout']['xaxis3'].update(title='Day of Year', range=[174, 256])
fig['layout']['yaxis1'].update(title='Degrees C',range=[-5,30])
fig['layout']['yaxis2'].update(title='mmol m<sup>-2</sup> m<sup>-d</sup>', range=[0, 35])
fig['layout']['yaxis3'].update(title='Ground Temps', range=[0, 11])
fig['layout']['yaxis4'].update(title='depth cm', range=[-20, 0])
fig['layout']['yaxis8'].update(title='rainfall cm', range=[0, 1.6])
fig['layout'].update(showlegend=False, title='Climate Conditions')
# In this example, I am only doing it for the last subplot, but if you wanted to do if for all,
# Just change to range(1,5)
for k in range(4,5):
fig['layout'].update({'yaxis{}'.format(k+4): dict(anchor='x'+str(k),
overlaying='y'+str(k),
side='right',
)
})
trace1 = go.Scatter(
y=Daily['AirTC_Avg'],
x=Daily.index,
marker = dict(
size = 10,
color = 'rgba(160, 0, 0, .8)',),
error_y=dict(
type='data',
array=Daily_Max['AirTC_Avg']-Daily_Min['AirTC_Avg'],
visible=True,
color = 'rgba(100, 0, 0, .5)',
),
name = 'Air Temp'
)
trace2 = go.Bar(
y=Daily['PPFD']/1000,
x=Daily.index,
name='Photon Flux',
marker=dict(
color='rgb(180, 180, 0)'
),
yaxis='y2',
)
trace3 = go.Scatter(
y=Daily['Temp_2_5_1'],
x=Daily.index,
name='Soil Temp',
marker=dict(
color='rgb(180, 0, 0)'
),
yaxis='y3',
)
trace4 = go.Scatter(
y=Daily['Table_1']*100,
x=Daily.index,
name='Water Table',
marker=dict(
color='rgb(0, 0, 180)'
),
yaxis='y4',
)
trace5 = go.Bar(
y=Daily['Rain']/10,
x=Daily.index,
name='Rain',
marker=dict(
color='rgb(0, 100, 180)'
),
yaxis='y8',
)
fig.append_trace(trace1, 1, 1)
fig.append_trace(trace2, 1, 2)
fig.append_trace(trace3, 2, 1)
fig.append_trace(trace4, 2, 2)
fig.append_trace(trace5, 2, 2)
## This part is important!!! you have to manually assing the data to the axis even
# though you do it when defining trace 5
fig['data'][4].update(yaxis='y'+str(8))
plot(fig, filename='FI_Climate')
Not an exact answer but I thought it might help...
I like to use pandas and cufflinks. Here is an example of how to plot two sets of data from one dataframe (df) on a graph using a secondary y axis. The data from each axis is displayed in different formats in this example (scatter and bar). The data is arranged into columns beforehand.
import pandas as pd
import cufflinks as cf
from plotly.offline import download_plotlyjs, init_notebook_mode,plot,iplot
fig1 = df.iplot(kind='scatter', mode='lines+markers', x=['col1', 'col2'],
y=['col3', 'col4',],
asFigure=True)
fig2 = df.iplot(kind='bar', x=['col1', 'col2'],
y=['col3', 'col4', ],
secondary_y=['col5','col6'],asFigure=True)
fig2['data'].extend(fig1['data'])
The naming convention is y, y2, y3... y40, and you make the reference to the axis in the trace dict.
So your traces should be like...
trace0 = dict(
x = xvals,
y = yvals,
yaxis = 'y'
)
trace1 = dict(
x = x2vals,
y = y2vals,
yaxis = 'y2'
)
....
trace40 = dict(
x = x40vals,
y = y40vals,
yaxis = 'y40'
)