I was just wondering if this can be done. I have tried to set the bins explicitly using numpy logspace, and I have also tried to set the xscale to 'log'. Neither of these options work. Has anybody ever tried this?
I just want a 2d histogram with a log x-axis and a linear y-axis.
pyplot library can be used to change the y-axis or x-axis scale to logarithmic respectively. The method yscale() or xscale() takes a single value as a parameter which is the type of conversion of the scale, to convert axes to logarithmic scale we pass the “log” keyword or the matplotlib. scale.
hist2d() Function. The hist2d() function in pyplot module of matplotlib library is used to make a 2D histogram plot. Syntax:matplotlib.pyplot.hist2d(x, y, bins=10, range=None, density=False, weights=None, cmin=None, cmax=None, \*, data=None, \*\*kwargs)
Use bar3d() method to plot 3D bars. To hide the axes use axis('off') class by name. To display the figure, use show() method.
The reason it's not working correctly is that plt.hist2d
uses the pcolorfast
method, which is much more efficient for large images, but doesn't support log axes.
To have a 2D histogram that works correctly on log axes, you'll need to make it yourself using np.histogram2d
and ax.pcolor
. However, it's only one extra line of code.
To start with, let's use exponentially spaced bins on a linear axis:
import numpy as np
import matplotlib.pyplot as plt
x, y = np.random.random((2, 1000))
x = 10**x
xbins = 10**np.linspace(0, 1, 10)
ybins = np.linspace(0, 1, 10)
fig, ax = plt.subplots()
ax.hist2d(x, y, bins=(xbins, ybins))
plt.show()
Okay, all well and good. Let's see what happens if we make the x-axis use a log scale:
import numpy as np
import matplotlib.pyplot as plt
x, y = np.random.random((2, 1000))
x = 10**x
xbins = 10**np.linspace(0, 1, 10)
ybins = np.linspace(0, 1, 10)
fig, ax = plt.subplots()
ax.hist2d(x, y, bins=(xbins, ybins))
ax.set_xscale('log') # <-- Only difference from previous example
plt.show()
Notice that the log scaling seems to have been applied, but the colored image (the histogram) isn't reflecting it. The bins should appear square! They're not because the artist created by pcolorfast
doesn't support log axes.
To fix this, let's make the histogram using np.histogram2d
(what plt.hist2d
uses behind-the-scenes), and then plot it using pcolormesh
(or pcolor
), which does support log axes:
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(1977)
x, y = np.random.random((2, 1000))
x = 10**x
xbins = 10**np.linspace(0, 1, 10)
ybins = np.linspace(0, 1, 10)
counts, _, _ = np.histogram2d(x, y, bins=(xbins, ybins))
fig, ax = plt.subplots()
ax.pcolormesh(xbins, ybins, counts.T)
ax.set_xscale('log')
plt.show()
(Note that we have to transpose counts
here, because pcolormesh
expects the axes to be in the order of (Y, X).)
Now we get the result we'd expect:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With