在matplotlib中手动绘制对数间距刻度线和标签

时间:2018-03-15 13:51:30

标签: python matplotlib

我经常发现自己在我的绘图的日志单元中工作,例如在装箱之前获取np.log10(x)数据或创建等高线图。问题是,当我想要绘制图表时,轴是丑陋的对数单位,刻度线均匀分布。

如果我让matplotlib进行所有转换,即设置ax.set_xaxis('log'),那么我会看到非常漂亮的轴,但是我不能对我的数据这样做,因为它是例如已经以日志单位分箱。我可以手动更改刻度标签,但这不会使刻度间距成对数。我想我也可以手动指定每个小刻度的位置,例如它有日志间距,但这是实现这一目的的唯一方法吗?这有点单调乏味,所以如果有更好的方法会很好。

具体情况,这是一个情节: enter image description here

我希望刻度标签为10^x10^y(所以' 1'是' 10',2是' 100&# 39;等等),我希望绘制次要刻度,因为ax.set_xaxis('log')会绘制它们。

编辑:为了进一步具体化,假设绘图是从图像生成的,如下所示:

import matplotlib.pyplot as plt
import scipy.misc
img = scipy.misc.face()

x_range = [-5,3] # log10 units
y_range = [-55, -45] # log10 units

p = plt.imshow(img,extent=x_range+y_range)

plt.show()

我们要做的就是改变轴的外观,如我所描述的那样。

编辑2:好的,重要性的回答欧文斯特的答案非常聪明,但它对图像的要求比我想要的要多一些。我有另一个例子,这次是分箱数据。也许他们的技术仍然适用于此,但我不清楚是否是这种情况。

import numpy as np
import pandas as pd
import datashader as ds
from matplotlib import pyplot as plt
import scipy.stats as sps

v1 = sps.lognorm(loc=0, scale=3, s=0.8)
v2 = sps.lognorm(loc=0, scale=1, s=0.8)
x = np.log10(v1.rvs(100000))
y = np.log10(v2.rvs(100000))
x_range=[np.min(x),np.max(x)]
y_range=[np.min(y),np.max(y)]

df = pd.DataFrame.from_dict({"x": x, "y": y})

#------ Aggregate the data ------
cvs = ds.Canvas(plot_width=30, plot_height=30, x_range=x_range, y_range=y_range)
agg = cvs.points(df, 'x', 'y')

# Create contour plot
fig = plt.figure()
ax = fig.add_subplot(111)
ax.contourf(agg, extent=x_range+y_range)
ax.set_xlabel("x")
ax.set_ylabel("y")

plt.show()

enter image description here

1 个答案:

答案 0 :(得分:2)

这个问题的一般答案可能在这篇文章中给出:

Can I mimic a log scale of an axis in matplotlib without transforming the associated data?

但是这里一个简单的选项可能是缩放轴的内容,然后将轴设置为对数刻度。

一种。图像

您可以在对数刻度上绘制图像,但以日志单位使所有像素的大小相同。很遗憾,imshow不允许使用此类图像(any more),但可以使用pcolormesh来实现此目的。

import numpy as np
import matplotlib.pyplot as plt
import scipy.misc
img = scipy.misc.face()

extx = [-5,3]     # log10 units
exty = [-45, -55] # log10 units
x = np.logspace(extx[0],extx[-1],img.shape[1]+1)
y = np.logspace(exty[0],exty[-1],img.shape[0]+1)
X,Y = np.meshgrid(x,y)

c =  img.reshape((img.shape[0]*img.shape[1],img.shape[2]))/255.0
m = plt.pcolormesh(X,Y,X[:-1,:-1], color=c, linewidth=0)
m.set_array(None)

plt.gca().set_xscale("log")
plt.gca().set_yscale("log")

plt.show()

enter image description here

B中。轮廓

相同的概念可用于等高线图。

import numpy as np
from matplotlib import pyplot as plt

x = np.linspace(-1.1,1.9)
y = np.linspace(-1.4,1.55)
X,Y = np.meshgrid(x,y)
agg = np.exp(-(X**2+Y**2)*2)


fig, ax  = plt.subplots()

plt.gca().set_xscale("log")
plt.gca().set_yscale("log")


exp = lambda x: 10.**(np.array(x))

cf = ax.contourf(exp(X), exp(Y),agg, extent=exp([x.min(),x.max(),y.min(),y.max()]))

ax.set_xlabel("x")
ax.set_ylabel("y")

plt.show()

enter image description here