I want to plot a graph with one logarithmic axis using matplotlib.
I've been reading the docs, but can't figure out the syntax. I know that it's probably something simple like 'scale=linear' in the plot arguments, but I can't seem to get it right
Sample program:
import pylab
import matplotlib.pyplot as plt
a = [pow(10, i) for i in range(10)]
fig = plt.figure()
ax = fig.add_subplot(2, 1, 1)
line, = ax.plot(a, color='blue', lw=2)
pylab.show()
You can use the Axes.set_yscale method. That allows you to change the scale after the Axes object is created. That would also allow you to build a control to let the user pick the scale if you needed to.
The relevant line to add is:
ax.set_yscale('log')
You can use 'linear' to switch back to a linear scale. Here's what your code would look like:
import pylab
import matplotlib.pyplot as plt
a = [pow(10, i) for i in range(10)]
fig = plt.figure()
ax = fig.add_subplot(2, 1, 1)
line, = ax.plot(a, color='blue', lw=2)
ax.set_yscale('log')
pylab.show()
First of all, it's not very tidy to mix pylab and pyplot code. What's more, pyplot style is preferred over using pylab.
Here is a slightly cleaned up code, using only pyplot functions:
from matplotlib import pyplot
a = [ pow(10,i) for i in range(10) ]
pyplot.subplot(2,1,1)
pyplot.plot(a, color='blue', lw=2)
pyplot.yscale('log')
pyplot.show()
The relevant function is pyplot.yscale(). If you use the object-oriented version, replace it by the method Axes.set_yscale(). Remember that you can also change the scale of X axis, using pyplot.xscale() (or Axes.set_xscale()).
Check my question What is the difference between ‘log’ and ‘symlog’? to see a few examples of the graph scales that matplotlib offers.
if you want to change the base of logarithm, just add:
plt.yscale('log',base=2)
Before Matplotlib 3.3, you would have to use basex/basey as the bases of log
You simply need to use semilogy instead of plot:
from pylab import *
import matplotlib.pyplot as pyplot
a = [ pow(10,i) for i in range(10) ]
fig = pyplot.figure()
ax = fig.add_subplot(2,1,1)
line, = ax.semilogy(a, color='blue', lw=2)
show()
I know this is slightly off-topic, since some comments mentioned the ax.set_yscale('log') to be "nicest" solution I thought a rebuttal could be due. I would not recommend using ax.set_yscale('log') for histograms and bar plots. In my version (0.99.1.1) i run into some rendering problems - not sure how general this issue is. However both bar and hist has optional arguments to set the y-scale to log, which work fine.
references:
http://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.bar
http://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.hist
So if you are simply using the unsophisticated API, like I often am (I use it in ipython a lot), then this is simply
yscale('log')
plot(...)
Hope this helps someone looking for a simple answer! :).
Related
I want to plot a graph with one logarithmic axis using matplotlib.
I've been reading the docs, but can't figure out the syntax. I know that it's probably something simple like 'scale=linear' in the plot arguments, but I can't seem to get it right
Sample program:
import pylab
import matplotlib.pyplot as plt
a = [pow(10, i) for i in range(10)]
fig = plt.figure()
ax = fig.add_subplot(2, 1, 1)
line, = ax.plot(a, color='blue', lw=2)
pylab.show()
You can use the Axes.set_yscale method. That allows you to change the scale after the Axes object is created. That would also allow you to build a control to let the user pick the scale if you needed to.
The relevant line to add is:
ax.set_yscale('log')
You can use 'linear' to switch back to a linear scale. Here's what your code would look like:
import pylab
import matplotlib.pyplot as plt
a = [pow(10, i) for i in range(10)]
fig = plt.figure()
ax = fig.add_subplot(2, 1, 1)
line, = ax.plot(a, color='blue', lw=2)
ax.set_yscale('log')
pylab.show()
First of all, it's not very tidy to mix pylab and pyplot code. What's more, pyplot style is preferred over using pylab.
Here is a slightly cleaned up code, using only pyplot functions:
from matplotlib import pyplot
a = [ pow(10,i) for i in range(10) ]
pyplot.subplot(2,1,1)
pyplot.plot(a, color='blue', lw=2)
pyplot.yscale('log')
pyplot.show()
The relevant function is pyplot.yscale(). If you use the object-oriented version, replace it by the method Axes.set_yscale(). Remember that you can also change the scale of X axis, using pyplot.xscale() (or Axes.set_xscale()).
Check my question What is the difference between ‘log’ and ‘symlog’? to see a few examples of the graph scales that matplotlib offers.
if you want to change the base of logarithm, just add:
plt.yscale('log',base=2)
Before Matplotlib 3.3, you would have to use basex/basey as the bases of log
You simply need to use semilogy instead of plot:
from pylab import *
import matplotlib.pyplot as pyplot
a = [ pow(10,i) for i in range(10) ]
fig = pyplot.figure()
ax = fig.add_subplot(2,1,1)
line, = ax.semilogy(a, color='blue', lw=2)
show()
I know this is slightly off-topic, since some comments mentioned the ax.set_yscale('log') to be "nicest" solution I thought a rebuttal could be due. I would not recommend using ax.set_yscale('log') for histograms and bar plots. In my version (0.99.1.1) i run into some rendering problems - not sure how general this issue is. However both bar and hist has optional arguments to set the y-scale to log, which work fine.
references:
http://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.bar
http://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.hist
So if you are simply using the unsophisticated API, like I often am (I use it in ipython a lot), then this is simply
yscale('log')
plot(...)
Hope this helps someone looking for a simple answer! :).
The following code generates a description of my dataset, plus a histogram, one on top of the other...
get_ipython().magic(u'matplotlib inline')
import matplotlib.pyplot as plt
import seaborn as sns
sns.distplot(dfx.hits, bins=20)
dfx.hits.describe()
(And not in the order that I'd expect.)
Here's the result:
But I want these figures side by side. Is this possible?
James' suggestion to use subplots is helpful, but it's not as detailed as the answer provided at this question:
How to Display Dataframe next to Plot in Jupyter Notebook
Charles Parr's answer there helped me write this code:
fig = plt.figure(figsize=(10,4))
ax1 = fig.add_subplot(121)
ax1.hist(dfx.hits, bins=20, color='black')
ax1.set_title('hits x users histogram')
dfxx = dfx.hits.describe().to_frame().round(2)
ax2 = fig.add_subplot(122)
font_size=12
bbox=[0, 0, 1, 1]
ax2.axis('off')
mpl_table = ax2.table(cellText = dfxx.values, rowLabels = dfxx.index, bbox=bbox, colLabels=dfxx.columns)
mpl_table.auto_set_font_size(False)
mpl_table.set_fontsize(font_size)
Which generated side-by-side subplots of a histogram and a description:
You're going to want to use matplotlib's built-in sub-plotting to make a (2,1) plot and place the first plot at (0,0) and the second at (1,0).
You can find the official documentation here which isn't great.
I'd recommend checking out the guide at python-course.eu here:
Also the reason its out of order is because you're not calling plt.show() or the seaborn equivalent and hence ipython is spitting the graph out last as it is called without being assigned somewhere else.
Similar to if you had:
import matplotlib.pyplot as plt
plt.plot(range(10),range(10))
print("hello")
The output is:
>>hello
>>'Some Graph here'
I have some code which produces a 3D scatter plot using matplotlib's scatter in conjunction with tight_layout, see the simplified code below:
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import proj3d
fig = plt.figure()
ax = fig.gca(projection='3d')
N = 100
x = np.random.random(N)
y = np.random.random(N)
z = np.random.random(N)
ax.scatter(x, y, z)
plt.tight_layout() # <-- Without this, everything is fine
plt.savefig('scatter.png')
In matplotlib 2.2.3 this makes a figure like so:
Similar output is generated by older versions, at least back to 1.5.1. When using the new version 3.0.0, something goes wrong at plt.tight_layout() and I get the following output:
Accompanying this is the warning
.../matplotlib/tight_layout.py:177: UserWarning: The left and right margins cannot be made large enough to accommodate all axes decorations
One may argue that using tight_layout with no arguments as here does not (on older matplotlibs) consistently lead to the expected tightened margins anyway, and so one should refrain from using tight_layout with 3D plots in the first place. However, by manually tweaking the arguments to tight_layout it is (used to be) a decent way to trim the margins even on 3D plots.
My guess is that this is a bug in matplotlib, but maybe they've made some deliberate change I havn't picked up on. Any pointers about a fix is appreciated.
Thanks to the comment by ImportanceOfBeingErnest, it now works:
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import proj3d
fig = plt.figure()
ax = fig.gca(projection='3d')
N = 100
x = np.random.random(N)
y = np.random.random(N)
z = np.random.random(N)
ax.scatter(x, y, z)
# The fix
for spine in ax.spines.values():
spine.set_visible(False)
plt.tight_layout()
plt.savefig('scatter.png')
From the links in the comment, it seems that this will be fixed in matplotlib 3.0.x. For now, the above may be used.
plt.tight_layout()
plt.show()
Right below your main body code of plotting.
I have seen several similar question but none which answers my precise question, so please bear with it before marking it duplicate.
I have to plot n lines on a graph.
The standard value of n is 10 but it can vary. Previously, I used
ax.set_color_cycle([plt.cm.Accent(i) for i in np.linspace(0, 1, limit)])
Which works well for me.
However, this method has depreciated as of late, and my program gives a warning for the same to use set_prop_cycle
I wasn't able to find any example in the documentation http://matplotlib.org/api/axes_api.html that suits my needs of uses a colour bar like accent or hot or cool etc.
Update
Sample code for testing:
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure()
ax = fig.add_subplot(111)
limit=10
ax.set_color_cycle([plt.cm.Accent(i) for i in np.linspace(0, 1, limit)])
for limit in range(1,limit+1):
x=np.random.randint(10, size=10)
y=limit*x
plt.plot(x,y,lw=2, label=limit)
plt.legend(loc='best')
What this shows me is:
The question is how can I use a colormap to chose between different shades of a color or the sort? http://matplotlib.org/users/colormaps.html
You need a slightly different formulation in order to make use of the more generic set_prop_cycle. You have to create a cycler for the argument 'color' with plt.cycler and for the rest do it exactly as you did before:
import matplotlib.pyplot as plt
import numpy as np
limit=10
fig = plt.figure()
ax = fig.add_subplot(111)
ax.set_prop_cycle(plt.cycler('color', plt.cm.Accent(np.linspace(0, 1, limit))))
for limit in range(1,limit+1):
x=np.random.randint(10, size=10)
y=limit*x
plt.plot(x,y,lw=2, label=limit)
plt.legend(loc='best')
Dear matplotlib community,
I have a very quick question regarding logarithmic axis labelling that I'm sure one of you could answer at the drop of a hat.
Essentially I have a log axis in matplotlib with labels of 10^-2, 10^-1, 10^0, 10^1, 10^2 etc
However, I would like 0.01, 0.1, 1, 10, 100.
Could anyone guide me on this. I have tried a few options, such as:
ax.set_xticks([0.01,0.1,1,10,100])
ax.set_xlabels([0.01,0.1,1,10,100])
Any pro tips would be greatly appreciated!
I think you want ax.xaxis.set_major_formatter(FormatStrFormatter("%g")), as in:
x=[0.1,1,10,100,1000]
y=[-1,0,1,2,3]
fig,ax=plt.subplots()
ax.plot(x,y,'.-')
ax.set_xscale('log')
ax.xaxis.set_major_formatter(FormatStrFormatter("%g"))
Example output:
A nice way is to use the FuncFormatter class of the matplotlib.ticker module. In conjunction with a custom function definition of your own making, this can help to customise your ticks to the exact way you want them. This particular bit of code works well with the logarithmic scale employed by matplotlib.
import numpy as np
import matplotlib.pylab as plt
x = np.linspace(-10,10)
y = np.exp(x)
plt.close('all')
fig,ax = plt.subplots(1,1)
ax.plot(x,y,'bo')
ax.set_yscale('log')
#Placed the import/function definitions here to emphasize
#the working lines of code for this particular task.
from matplotlib.ticker import FuncFormatter
def labeller(x, pos):
"""
x is the tick value, pos is the position. These args are needed by
FuncFormatter.
"""
if x < 1:
return '0.'+'0'*(abs(int(np.log10(x)))-1)+\
format(x/10**(np.floor(np.log10(x))),'.0f')
else:
return format(x,'.0f')
#FuncFormatter class instance defined from the function above
custom_formatter = FuncFormatter(labeller)
ax.yaxis.set_major_formatter(custom_formatter)
plt.show()
Result:
First, instead of set_xlabels you should call set_xticklabels for the actual tick labels. That said, at least in my current environment (python 2.7, matplotlib 1.4.3, OS X 10.10) that is not always enough. When doing instruction by instruction in a REPL (e.g. ipython) sometimes is necessary to update the axis after calling set_xticklabels. A quick hack to do that is to simply call grid(True) or grid(False). For example:
x = np.logspace(-2,2, 1000)
y = np.sin(x)
l = [0.01,0.1,1,10,100]
plt.semilogx(x,y)
plt.gca().set_xticks(l)
plt.gca().set_xticklabels(l)
plt.grid(True)
Empirical note: the grid(False) trick doesn't seem to be necessary when pasting that gist using ipython's %paste magic (anybody know why?)