I am drawing a scatter plot using matplotlib. This is a somewhat peculiar issue. Here's the plot of the data when there is no scale of the axes
plt.scatter(x, y , marker ='x')
#plt.xscale('log')
#plt.yscale('log')
plt.show()
The plot of the data with axes scaled to `logarithm' scale.
Why is this happening? The same happens even when the base is changed to 2 or e
It appears that in this particular case, you can't scale the axes after the plot. You can scale them beforehand, so:
plt.xscale('log')
plt.yscale('log')
plt.scatter(x, y , marker ='x')
plt.show()
In this particular case (identical markers), you could also use plt.plot instead of plt.scatter, and then scaling post-plot will work:
plt.plot(x, y, 'x')
plt.xscale('log')
plt.yscale('log')
plt.show()
My guess as to why you can't scale post scatter plot: a scatter plot returns a PathCollection, which probably results in the scaling function looking only at the last entry of that collection, that is, the last point. That would of course scale only in the range 1e5 - 1e6. plot() returns a Line2D, which takes the complete plot into account.
The log scaling should clip values sensibly so 0 in the data are not the problem.
I suspect the issue is that your limits have negative values so naively taking the log of the limits and using those causes issues.
You can also explicitly set the limit
ax = plt.gca()
ax.set_xlim([1e-5, 1e6])
ax.set_ylim([1e-5, 1e6])
and not rely on auto-scaling.
Related
I'm trying to plot various trig functions with sympy. This works fine with sine, cosine, etc., but tan() displays wierd results. Furthermore, if I rerun just the plot() function, then I get a different result each time.
from sympy import symbols
from sympy.functions.elementary.trigonometric import tan
from sympy.plotting.plot import plot
x = symbols('x')
eqn = tan(x)
plot(eqn, (x, -10, 10))
I understand that this is not how one usually visualizes the tangent function:
but it's not wrong. SymPy found that there are extremely large y-values, and chose the vertical scale accordingly. On this scale, all values are practically zero except in close proximity to the singularities. And the unequal height of spikes near singularities is because the evaluation points are not going to hit any pi/2 + pi*n exactly, and how close they come depends on what n is.
All that said, you need a sane vertical scale, enforced with ylim:
plot(eqn, (x, -10, 10), ylim=(-20, 20))
I'm having trouble creating a colorbar for my plot in Python using matplotlib. I am using a colormap, not to colour all the data that I plot but to extract a colour for a plot based on a value I'm not plotting. Hope this makes sense..
So I'm in a for loop, create a plot every time with a colour based on a certain parameter. Like this (the data is an example to create an mwe, my data is more complicated):
import matplotlib as mpl
from matplotlib import pyplot as plt
import numpy as np
xdata = np.array(range(10))
parameter = [0.5, 0.3, 0.78, 0.21, 0.45] #random parameter example
cmap = mpl.cm.get_cmap('jet')
for i in range(len(parameter)):
clr = cmap(parameter(i))
plt.plot(xdata,xdata**i,c=clr)
plt.show()
Now, what I would want is a colorbar on the side (or actually two, but that's another problem I think) that shows the jet colormap and according values. The values need to be scaled to a new min and max value.
So far I've found the following, but I don't understand it enough to apply it to my own problem:
Getting individual colors from a color map in matplotlib
Which told me how to extract the colour and shows how to create the normalized colormap
Colorbar only
Which should tell me how to add a colorbar without using the plotted data, but I don't understand enough of it. My problem is with the creation of the axes. I don't understand this part if I want to put the colorbar next to my plot. In the example they create a figure with handle fig, but in my case the figure is created when I do plt.imshow(image), since this is what I start with and then I'm plotting over the image. I cannot use the fig.add_axes here.
I hope you can help me out here. It would be great if I could also create a 'reversed' colorbar. So either the colours are in reverse direction, or the values next to the bar.
At any point in the script you can get the figure via fig = plt.gcf() and an axes via ax=plt.gca(). So, adding an axes may be done by plt.gcf().add_axes(...).
There is also nothing wrong with putting fig=plt.figure() before plotting anything.
Note that after creating a new axes, plt.gca() will return the new axes, so it is a good idea to create a reference to the main axes before adding a new one.
A convenient way to obtain a figure and an axes for later referencing is to create the figure via
fig, ax = plt.subplots()
Colormaps:
Every standard colormap has a reversed version, which has _r at the end of its name, e.g. you can use viridis_r instead of viridis.
I have two independent datasets, z_p and z_g here, and I would like to put two tricontourf() instances on the same axis, each instance corresponding to a contour of one dataset. Below is a pseudo-code of what I do:
cmap_p = plt.get_cmap('Reds')
norm_p = BoundaryNorm(levels, ncolors=cmap_p.N, clip=True)
cmap_g = plt.get_cmap('Blues')
norm_g = BoundaryNorm(levels, ncolors=cmap_g.N, clip=True)
lev = range(lower_level, upper_level+1)
obj_g = ax.tricontourf(x, y, z_g, cmap=cmap_g, norm=norm_g,
levels=lev, extent=[x0, y0, x1, y1], zorder=2)
obj_p = ax.tricontourf(x, y, z_p, cmap=cmap_p, norm=norm_p,
levels=lev, extent=[x0, y0, x1, y1], zorder=3)
The output figure is attached below. Clearly, only the second call to tricontourf() has effectively worked, since there is a patch on the left of the figure in red. If I comment out the call to get obj_p, then I get a blue patch on the right side of the figure in blue color. However, the two subsequent calls to tricontourf() do not work simultaneously.
I would be grateful if someone would tell me how to show both contours on the same axis?
Your second plot is covering up the first plot with an opaque white color, which is why you see the first one when you don't plot the second. If you want to see both, you can set the alpha keyword:
alpha=0.5
to make the plots transparent enough to see through. Alternatively, there is an answer at this SO question about masking a call to tricontourf, if you know where the overlapping region is and want to simply mask it out of the second plot.
For some reason, I just can't get this to work. What I end up getting is two grids with axes plotted on top of each other and then the second plot plotted under this. My code works fine for a seaborn distplot:
plt.subplot(121)
h = sns.distplot(dfmain["Runs"])
plt.subplot(122)
j = sns.distplot(dfHighScores["Runs"])
But if I try and plot two factor plots side by side (they are independent so I don't want the axes to be shared), then this just doesn't work as described above:
plt.subplot(121)
h = sns.factorplot("Runs",data=dfmain)
plt.subplot(122)
j = sns.factorplot("Runs",data=dfHighScores)
I get this behavior whether I use an iPython notebook or spyder as my IDE. Any help would be greatly appreciated.
According to the documentation of factorplot it should be able do draw two plots side by side by itself. If you combine both your data frames into one (and add a column to tell between them) then something like this should work:
sns.factorplot("Runs", col="mainOrHighScores", data=dfCombined)
Otherwise I think factorplot doesn't operate on axes (unlike distplot).
In any case only functions that have an "ax" parameter for axes can draw on axes.
I have two numpy arrays of sizes (Number_of_time_steps, N1, N2). Each one represents velocities in a plane of size N1xN2 for Number_of_time_steps which is 12,000 in my case. These two arrays come from two fluid dynamics simulations in which a point is slightly perturbed at time 0 and I want to study the discrepancies caused by the perturbation in the velocity of each point in the grid. To do so, for each time step, I make a plot with 4 subplots: pcolor map of plane 1, pcolor map of plane 2, difference between the planes, and difference between the planes in log scale. I use matplotlib.pyplot.pcolor to create each subplot.
This is something that can be easily done, but the problem is that I will end up with 12,000 of such plots (saved as .png files on the disk). Instead, I want a kind of interactive plot in which I can enter the time step, and it will update the 4 subplots to the corresponding time step from the values in the two existing arrays.
If somebody has any idea on how to solve this problem, be happy to hear about it.
For interactive graphics, you should look into Bokeh:
http://docs.bokeh.org/en/latest/docs/quickstart.html
You can create a slider that will bring up the time slices you want to see.
If you can run from within ipython, you could just make a function to plot your given timestep
%matplotlib # set the backend
import matplotlib.pyplot as plt
fig,((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2, sharex='col', sharey='row')
def make_plots(timestep):
# Clear the subplots
[ax.cla() for ax in [ax1,ax2,ax3,ax4]]
# Make your plots. Add whatever options you need
ax1.pcolor(array1[timestep])
ax2.pcolor(array2[timestep])
ax3.pcolor(array1[timestep]-array2[timestep])
ax4.pcolor(array1[timestep]-array2[timestep])
# Make axis labels, etc.
ax1.set_xlabel(...) # etc.
# Update the figure
fig.show()
# Plot some timesteps like this
make_plots(0) # time 0
# wait some time, then plot another
make_plots(100) # time 100
make_plots(12000) # time 12000