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
Related
I want use a for cycle to call a charting function and then represent the outcome chart into a section of a multi charting pageExample single chart
expected outcome
I have a charting function (see below Charting Function Section) that i recall in a the main script with a for cycle to get several charts in sequence. Now I would like to represent all the charts, in compact size (2 columns 4 rows) in one single page. In literature I find that Subplot allows me to do so but I struggle to find the right command to represent the outcome from the charting function.
I thought something like the below in the Main Section would work but it is not
---------- Main Section ---------
import pandas as pd
import numpy as np
import plotly.graph_objs as go
from sklearn.cluster import KMeans
from plotly.subplots import make_subplots
for cont in range(8):
fig = charting_func(cont)
fig_all.add_trace(fig,
row=1, col=1
) #row and col incrementing function to be defined
fig_all.update_layout(height=600, width=800, title_text="Side By Side Subplots")
fig_all.show()
----- Charting Function ------
def charting_func(n_chrt):
# Arbitrarily 10 colors for up to 10 clusters
#colors = ['red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet', 'purple','pink', 'silver']
# Create Scatter plot, assigning each point a color where
# point group = color index.
fig = btc.plot.scatter(
x=btc.index,
y="Adj Close",
color=[colors[i] for i in lists_clusters[n_chrt]],
title="k-values = {0}".format(n_chrt+2)
)
# Add horizontal lines
for cluster_avg in output[n_chrt][1:-1]:
fig.add_hline(y=cluster_avg, line_width=1, line_color="blue")
# Add a trace of the price for better clarity
fig.add_trace(go.Scatter(
x=btc.index,
y=btc['Adj Close'],
line_color="black",
line_width=1
))
# Make it pretty
layout = go.Layout(
plot_bgcolor='#D9D9D9',
showlegend=False,
# Font Families
font_family='Monospace',
font_color='#000000',
font_size=20,
xaxis=dict(
rangeslider=dict(
visible=False
))
)
fig.update_layout(layout)
return fig
type here
The basic form of a subplot is to add a location arrangement to the graph setup. So the functionalization needs to have matrix information or something like that. I have no data to present, so I have taken the stock prices of 4 companies and graphed them. As for the clustering by price, it is not included in the code, so the binning process is used to get the values and labels for the horizontal line. Please rewrite this part to your own logic. If you are good enough, the functionalization should work well.
import pandas as pd
import plotly.graph_objects as go
from plotly.subplots import make_subplots
import itertools
import yfinance as yf
stock = ['TSLA','MSFT','AAPL','AMD']
#fig = go.Figure()
fig = make_subplots(rows=2, cols=2, subplot_titles=['MSFT','TSLA','AMD','AAPL'])
for s,rc in zip(stock, itertools.product([1,2],[2,1])):
#print(s, rc[0], rc[1])
df = yf.download(s, start="2017-09-01", end="2022-04-01", interval='1mo', progress=False)
colors = ['blue', 'red', 'green', 'purple', 'orange']
s_cut, bins = pd.cut(df['Adj Close'], 5, retbins=True, labels=colors)
fig.add_trace(go.Scatter(mode='markers+lines',
x=df.index,
y=df['Adj Close'],
marker=dict(
size=10,
color=s_cut.tolist()
)),
row=rc[0], col=rc[1]
)
for b in bins[1:-1]:
fig.add_hline(y=b, line_width=1, line_color="blue", row=rc[0], col=rc[1])
fig.update_layout(autosize=True, height=600, title_text="Side By Side Subplots")
fig.show()
I am trying to make a function using plotly 5.9.0 that will reproduce a specific type of plot. I am having trouble aligning legend entries with their subplots, especially when the figure is resizable.
This is what i currently have:
import pandas as pd
import numpy as np
import plotly.graph_objects as go
import plotly.subplots as sp
from plotly.offline import plot
def get_df(len_df):
x = np.linspace(-1, 1, len_df)
# Create a dictionary with the functions to use for each column
funcs = {
"column1": np.sin,
"column2": np.cos,
"column3": np.tan,
"column4": np.arcsin,
"column5": np.arccos,
"column6": np.arctan
}
# Create an empty dataframe with the same index as x
df = pd.DataFrame(index=pd.date_range('2022-01-01', periods=len(x), freq='H'))
# Populate the dataframe with the functions
for column, func in funcs.items():
df[column] = func(x)
return df
def plot_subplots(df, column_groups, fig_height=1000):
# Create a figure with a grid of subplots
fig = sp.make_subplots(rows=len(column_groups), shared_xaxes=True, shared_yaxes=True, vertical_spacing=.1)
# Iterate over the list of column groups
for i, group in enumerate(column_groups):
# Iterate over the columns in the current group
for column in group:
# Add a scatter plot for the current column to the figure, specifying the row number
fig.add_trace(go.Scatter(x=df.index, y=df[column], mode="lines", name=column, legendgroup=str(i)), row=i + 1, col=1)
fig.update_layout(legend_tracegroupgap=fig_height/len(column_groups), height=fig_height)
return fig
df = get_df(1000)
column_groups = [
['column1', 'column3'],
['column2', 'column4'],
['column5', 'column6']
]
fig = plot_subplots(df, column_groups)
plot(fig)
This produces a plot that looks like this:
How do I align my legend subgroups with the top of each corresponding plotly subplot?
If we can somehow relate the legend_tracegroupgap to the height of the figure that would be a great first step. This feels like such a logical thing to want that I feel like I'm missing something.
In reply to r-beginners:
I tried this:
tracegroupgap=(fig.layout.yaxis.domain[1] - fig.layout.yaxis.domain[0])*fig_height
Which works perfectly for a figure with a height of 1000. But not for a height of 500 pixels. I still have to subtract some value that has to do with the vertical spacing is my guess.
There are few functions in plotly that allow strict size definitions other than figure size. The position of the legend in a subplot can also only be set by setting the spacing between legend groups as a pixel value (the default is 10px). So I used a function provided for development to check the area of the subplot.
dev_fig = fig.full_figure_for_development()
'yxais':{
...
domain': [0.7333333333333334, 1],
...
}
'yaxis2': {
...
'domain': [0.3666666666666667, 0.6333333333333333],
...
}
'yaxis3': {
...
'domain': [0, 0.26666666666666666],
...
}
fig.update_layout(legend_tracegroupgap=266, height=fig_height)
Since each subplot is drawn to the nearest 0.26 units, the gap was set at 266. However, this does not mean that we have derived a perfect value. I am sure other factors are still affecting this, and I hope to get answers from actual developers and others.
Question has been updated so that if the height of the graph is 500px
The default margins are 100px top and 80px bottom, so set them to 0.
def plot_subplots(df, column_groups, fig_height=500):
# Create a figure with a grid of subplots
fig = sp.make_subplots(rows=len(column_groups), shared_xaxes=True, shared_yaxes=True, vertical_spacing=.1)
# Iterate over the list of column groups
for i, group in enumerate(column_groups):
# Iterate over the columns in the current group
for column in group:
# Add a scatter plot for the current column to the figure, specifying the row number
fig.add_trace(go.Scatter(x=df.index, y=df[column], mode="lines", name=column, legendgroup=str(i)), row=i + 1, col=1)
tracegroupgap = (fig.layout.yaxis.domain[1] - fig.layout.yaxis.domain[0])*fig_height
print(fig.layout.yaxis.domain[0], fig.layout.yaxis.domain[1])
print(tracegroupgap)
fig.update_layout(margin=dict(t=0,b=0,l=0,r=0))
fig.update_layout(legend_tracegroupgap=tracegroupgap, height=fig_height)#fig_height/len(column_groups)
return fig
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 have plotted a figure with 2 subplots, each with different scales. Everything plots correctly, except the colorscales are both plotted on the right and completely overlap - they are are not readable. I cannot find out how to position/reposition the individual subplot scales. I have included my code below. Thanks.
import pandas as pd
import plotly.graph_objects as go
from plotly.subplots import make_subplots
df = pd.read_csv(entry)
custColorscale = [[0, 'green'], [0.5, 'red'], [1, 'rgb(50, 50, 50)']]
fig = make_subplots(
rows=1, cols=2, subplot_titles=('one', 'two'))
fig.add_trace(
go.Scatter(x=df['tO'],
y=df['t1'],
mode='markers',
marker=dict(colorscale=custColorscale,
cmin=0, cmax=2,
size=6, color=df['Var1'],
showscale=True),
text=df['Var2']),
1, 1)
fig.add_trace(
go.Scatter(x=df['tO'],
y=df['t1'],
mode='markers',
marker=dict(
size=6, color=df['Var2'],
showscale=True),
text=df['Var2']),
1, 2)
fig.update_layout(height=700, width=1900,
title='Raw data')
fig.update_layout(coloraxis=dict(
colorscale='Bluered_r'))
fig.write_html(fig, file='raw plots.html', auto_open=True)
Looking through the Plotly documentation you find this which provide some hints as to how to solve the problem. Scroll to the 'marker' attributes and you will find that it has sub-attribute called 'colorbar'. The colorbar in turn has multiple options that could help set the plot the way you want. Particularly you find the 'x', 'y' and 'len' attributes of the colorbar very useful. You can use them to position the scales.
This question is also related to this but for a contour plot - you are making a scatterplot which is why the scatterplot reference would be what one should search.
A minimal working example (MWE) is shown below but with a toy dataset.
## make necessary imports
import numpy as np
from plotly.subplots import make_subplots
import plotly.graph_objects as go
import pandas as pd
## make a fake dataset with pandas
d = {'t0': [i for i in np.arange(0.,10.,1.)], 't1': [i for i in
np.arange(10.,20.,1.)],'Var1': [i for i in np.arange(20.,30.,1.)],'Var2':
[i for i in np.arange(30.,40.,1.)] }
df = pd.DataFrame(data=d) #the dataset is made to mock the example code you provided
And for your plot you have the following :
# make subplots
custColorscale = [[0, 'green'], [0.5, 'red'], [1, 'rgb(50, 50, 50)']]
fig = make_subplots(
rows=1, cols=2, subplot_titles=('one', 'two'),horizontal_spacing = 0.4)
# plot 1
fig.add_trace(
go.Scatter(x=df['t0'],
y=df['t1'],
mode='markers',
marker=dict(colorscale=custColorscale,
cmin=0, cmax=2,
size=6, color=df['Var1'],
showscale=True,colorbar=dict(len=1.05, x=0.35
,y=0.49)), text=df['Var2']), 1, 1)
## plot 2
fig.add_trace(
go.Scatter(x=df['t0'],
y=df['t1'],
mode='markers',
marker=dict(
size=6, color=df['Var2'],
showscale=True,colorbar=dict(len=1.05, x=1.2 , y=0.49)),
text=df['Var2']),
1, 2 )
# show plots
fig.update_layout(height=500, width=700,
title='Raw data')
fig.update_layout(coloraxis=dict(
colorscale='Bluered_r'))
fig.show()
The only additions were:
The colorbar attribute of the marker.
The horizontal spacing to allow space for the first scale.
Feel free to play with these attributes.
I hope this helps!
Best regards.
I have the following code:
import numpy as np
import pandas as pd
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
matplotlib.style.use('ggplot')
import seaborn as sns
sns.set(style="white")
# Create a dataset with many short random walks
rs = np.random.RandomState(4)
pos = rs.randint(-1, 2, (10, 5)).cumsum(axis=1)
pos -= pos[:, 0, np.newaxis]
step = np.tile(range(5), 10)
walk = np.repeat(range(10), 5)
df = pd.DataFrame(np.c_[pos.flat, step, walk],
columns=["position", "step", "walk"])
# Initialize a grid of plots with an Axes for each walk
grid = sns.FacetGrid(df, col="walk", hue="walk", col_wrap=5, size=5,
aspect=1)
# Draw a bar plot to show the trajectory of each random walk
grid.map(sns.barplot, "step", "position", palette="Set3").add_legend();
grid.savefig("/Users/mymacmini/Desktop/test_fig.png")
#sns.plt.show()
Which makes this plot:
As you can see I get the legend wrong. How can I make it right?
Some how there is one legend item for each of the subplot. Looks like if we want to have legend corresponds to the bars in each of the subplot, we have to manually make them.
# Let's just make a 1-by-2 plot
df = df.head(10)
# Initialize a grid of plots with an Axes for each walk
grid = sns.FacetGrid(df, col="walk", hue="walk", col_wrap=2, size=5,
aspect=1)
# Draw a bar plot to show the trajectory of each random walk
bp = grid.map(sns.barplot, "step", "position", palette="Set3")
# The color cycles are going to all the same, doesn't matter which axes we use
Ax = bp.axes[0]
# Some how for a plot of 5 bars, there are 6 patches, what is the 6th one?
Boxes = [item for item in Ax.get_children()
if isinstance(item, matplotlib.patches.Rectangle)][:-1]
# There is no labels, need to define the labels
legend_labels = ['a', 'b', 'c', 'd', 'e']
# Create the legend patches
legend_patches = [matplotlib.patches.Patch(color=C, label=L) for
C, L in zip([item.get_facecolor() for item in Boxes],
legend_labels)]
# Plot the legend
plt.legend(handles=legend_patches)
When the legend doesn't work out you can always make your own easily like this:
import matplotlib
name_to_color = {
'Expected': 'green',
'Provided': 'red',
'Difference': 'blue',
}
patches = [matplotlib.patches.Patch(color=v, label=k) for k,v in name_to_color.items()]
matplotlib.pyplot.legend(handles=patches)