I have the following plot done in Plotly
As you can see the X,Y axis are in the traditional way.
How can I rotate the axis so that X is plot vertically and Y horizontally (to the left)?
(also I would like to modify the reach and separations of each axis)
I suppose it has to do something with the layout element.
My code if so far
layout= go.Layout(title=go.layout.Title(text=title,x=0.5),
xaxis={'title':'x[m]'},
yaxis={'title':'y[m]'})
point_plot=[
go.Scatter(x=[series[listoflabels[0]]],y=[series[listoflabels[1]]],name="V0"),
go.Scatter(x=[series[listoflabels[2]]],y=[series[listoflabels[3]]],name="GT"),
go.Scatter(x=[0],y=[0],name="egoCar")
]
return go.Figure(data=point_plot, layout=layout)
EDIT:
In order to make it reproducible I modified the code to
layout1= go.Layout(title=go.layout.Title(text="A graph",x=0.5),
xaxis={'title':'x[m]'},
yaxis={'title':'y[m]'})
point_plot=[
go.Scatter(x=[3],y=[1],name="V0"),
go.Scatter(x=[5],y=[2],name="GT"),
go.Scatter(x=[0],y=[0],name="egoCar")
]
go.Figure(data=point_plot, layout=layout1).show()
and the plot is
I am not aware that Plotly has any built-in method to switch x- and y-axes. However, you can achieve this yourself but switching the titles of the x- and y-axes, then switching the parameters x and y that correspond to your points.
Then you can place the y-axis (containing your x-coordinates) on the right side in your layout, and reverse the range of the x-axis (containing your y-coordinates) so that the origin is in the lower-right side.
import plotly.graph_objects as go
# switch the axes titles
layout1= go.Layout(title=go.layout.Title(text="A graph",x=0.5),
xaxis={'title':'y[m]'},
yaxis={'title':'x[m]', 'side':'right'})
# switch the x- and y-coordinates
point_plot=[
go.Scatter(y=[3],x=[1],name="V0"),
go.Scatter(y=[5],x=[2],name="GT"),
go.Scatter(y=[0],x=[0],name="egoCar")
]
fig = go.Figure(data=point_plot, layout=layout1)
# reverse the range of the xaxis (which contains the y values)
fig.update_xaxes(autorange="reversed")
fig.show()
Derek O hit on what is the easiest to implement. It's the graph analogy of 1km is 0.6 miles or a, b = b, a
A second option is to abstract the data and your axes. That's essentially saying the same thing but can be easier to read as Plotly has a unique ability to turn clear, well-structured Python into ugly JS without parenthesis pretty quickly.
Option three is to further abstract this and have it set your axes for you.
Related
I'm making a map using matplotlib.pyplot and I used the gridlines feature to create "labels" on the x and y axis of degrees latitude and longitude. I set the gridlines color to "none" to avoid having the gridlines there. However, these labels appear on each side of the plot and, at one point, coincide with my colorbar. Is there a way I could make these gridline labels only appear on the bottom and left of the plot? I can't find a list of the available kwargs anywhere. This is the code I used:
ax.gridlines(draw_labels=True, color="none")
And here is an image of the map. I would ideally like to remove the degree labels on the right and top axes.
You can achieve what you need with these relevant code:-
# minor change to the existing line of code
gls = ax.gridlines(draw_labels=True, color="none")
# other lines of code
# add these before plotting
gls.top_labels=False # suppress top labels
gls.right_labels=False # suppress right labels
I plotted the following using plotly and got the resulting plot shown before. X is the # of hours in a day, Y is a proportion between 0-1, and Z is a categorical variable with levels {0,1,2}.
However, it's unclear why the X seems to be going the opposite direction of what we're used to with a 3D Cartesian place where it's down(-) and up(+), left(-) and right(+), and front(-) and back(+). However, X seems to decrease from front to back instead of increase. I am new to plotly and am not sure how to flip the axis so it goes from 0 to 1 instead of 1 to 0. I would greatly appreciate help on this!
fig = px.scatter_3d(X_combined, x='x', y='y', z='z',
color='set', symbol='predictions', opacity=0.7)
fig.update_traces(marker=dict(size=12,
line=dict(width=5,
color='Black')),
selector=dict(mode='markers'))
For 3D plots, the options for axes are under layout.scene.
The autorange option is therefore located under layout.scene.xaxis.autorange and can be modified like this:
fig.update_scenes(xaxis_autorange="reversed")
References:
python/3d-axes
python/layout-scene-xaxis-autorange
This should do the trick:
fig.update_xaxes(autorange="reversed")
Alternatively, you can reverse it with a specific range:
fig.update_xaxes(range=[9, 3])
Let's look at a swarmplot, made with Python 3.5 and Seaborn on some data (which is stored in a pandas dataframe df with column lables stored in another class. This does not matter for now, just look at the plot):
ax = sns.swarmplot(x=self.dte.label_temperature, y=self.dte.label_current, hue=self.dte.label_voltage, data = df)
Now the data is more readable if plotted in log scale on the y-axis because it goes over some decades.
So let's change the scaling to logarithmic:
ax.set_yscale("log")
ax.set_ylim(bottom = 5*10**-10)
Well I have a problem with the gaps in the swarms. I guess they are there because they have been there when the plot is created with a linear axis in mind and the dots should not overlap there. But now they look kind of strange and there is enough space to from 4 equal looking swarms.
My question is: How can I force seaborn to recalculate the position of the dots to create better looking swarms?
mwaskom hinted to me in the comments how to solve this.
It is even stated in the swamplot doku:
Note that arranging the points properly requires an accurate transformation between data and point coordinates. This means that non-default axis limits should be set before drawing the swarm plot.
Setting an existing axis to log-scale and use this for the plot:
fig = plt.figure() # create figure
rect = 0,0,1,1 # create an rectangle for the new axis
log_ax = fig.add_axes(rect) # create a new axis (or use an existing one)
log_ax.set_yscale("log") # log first
sns.swarmplot(x=self.dte.label_temperature, y=self.dte.label_current, hue=self.dte.label_voltage, data = df, ax = log_ax)
This yields in the correct and desired plotting behaviour:
I am trying to plot a 3x3 sns.PairGrid of plots. Currently, the axes are shared for the bottom triangle, and the upper triangle separately. Put another way, the x axes and y axes are only shared with their respective columns/row. So the x-axis of plot (1,0) is shared with (0,0) and (2,0).
However, I would like all the off-diagonal plots to share their axes. So for example, I want (1,0) share its x-axis with (0,0) and (2,0) like before, but also with (0,1).
Also, I would prefer it if the y-axes aren't shared with the plots on the diagonal, as those are 1-D kernel density plots, and so if I share their y-axes, some of them will be invisible as the size of the probability density functions isn't the same.
Here's my current code if it helps:
The 3 parameters I am plotting against each other are called 'A', 'C', and 'logsw', and are contained in the pandas.DataFrame called hyperparams
g = sns.PairGrid(hyperparams, diag_sharey=False)
g.map_lower(sns.kdeplot)
g.map_upper(plt.scatter, marker='+')
g.map_diag(sns.kdeplot)
And here's a trivial example of the output plot:
The images on the bottom left are scaled differently to the images on the upper right, which is what I'm trying to avoid.
High level, you could manually set the x and y limits and tickmarks. You could also set variables to what you want to share and then just reuse the variable in the 3 like subplots.
That way, if you need to make an adjustment, you just update the variable and the 3 plots that share it now update all at once.
In the past, I created code for a Pair grid where I set the limits and ticks on all subplots along the y-axis, and all plots along the x-axis in this manner.
There is currently no way of automatically doing this in Seaborn. The workaround suggested in the comment that seems to have solve the problem is to set the axes limits manually for the diagonal subplots. Using variables for the x and y limits ensures that they only need to be changed in one place when updating the axes ranges.
I have a pair of lists of numbers representing points in a 2-D space, and I want to represent the y/x ratios for these points as a 1-dimensional heatmap, with a diverging color map centered around 1, or the logs of my ratios, with a diverging color map centered around 0.
How do I do that?
My current attempt (borrowing somewhat from Heatmap in matplotlib with pcolor?):
from matplotlib import numpy as np
import matplotlib.pyplot as plt
# There must be a better way to generate arrays of random values
x_values = [np.random.random() for _ in range(10)]
y_values = [np.random.random() for _ in range(10)]
labels = list("abcdefghij")
ratios = np.asarray(y_values) / np.asarray(x_values)
axis = plt.gca()
# I transpose the array to get the points arranged vertically
heatmap = axis.pcolor(np.log2([ratios]).T, cmap=plt.cm.PuOr)
# Put labels left of the colour cells
axis.set_yticks(np.arange(len(labels)) + 0.5, minor=False)
# (Not sure I get the label order correct...)
axis.set_yticklabels(labels)
# I don't want ticks on the x-axis: this has no meaning here
axis.set_xticks([])
plt.show()
Some points I'm not satisfied with:
The coloured cells I obtain are horizontally-elongated rectangles. I would like to control the width of these cells and obtain a column of cells.
I would like to add a legend for the color map. heatmap.colorbar = plt.colorbar() fails with RuntimeError: No mappable was found to use for colorbar creation. First define a mappable such as an image (with imshow) or a contour set (with contourf).
One important point:
matplotlib/pyplot always leaves me confused: there seems to be a lot of ways to do things and I get lost in the documentation. I never know what would be the "clean" way to do what I want: I welcome suggestions of reading material that would help me clarify my very approximative understanding of these things.
Just 2 more lines:
axis.set_aspect('equal') # X scale matches Y scale
plt.colorbar(mappable=heatmap) # Tells plt where it should find the color info.
Can't answer your final question very well. Part of it is due to we have two branches of doing things in matplotlib: the axis way (axis.do_something...) and the MATLAB clone way plt.some_plot_method. Unfortunately we can't change that, and it is a good feature for people to migrate into matplotlib. As far as the "Clean way" is concerned, I prefer to use whatever produces the shorter code. I guess that is inline with Python motto: Simple is better than complex and Readability counts.