matplotlib 等高线图:对数刻度中的比例颜色条级别

Posted

技术标签:

【中文标题】matplotlib 等高线图:对数刻度中的比例颜色条级别【英文标题】:matplotlib contour plot: proportional colorbar levels in logarithmic scale 【发布时间】:2013-08-14 01:15:30 【问题描述】:

是否可以像下图那样以对数刻度显示颜色条的级别?

下面是一些可以实现的示例代码:

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.colors import LogNorm
delta = 0.025

x = y = np.arange(0, 3.01, delta)
X, Y = np.meshgrid(x, y)
Z1 = plt.mlab.bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0)
Z2 = plt.mlab.bivariate_normal(X, Y, 1.5, 0.5, 1, 1)
Z = 1e6 * (Z1* Z2)

fig=plt.figure()
ax1 = fig.add_subplot(111)
lvls = np.logspace(0,4,20)
CF = ax1.contourf(X,Y,Z,
         norm = LogNorm(),
         levels = lvls
        )
CS = ax1.contour(X,Y,Z,
         norm = LogNorm(),
         colors = 'k',
         levels = lvls
        )
cbar = plt.colorbar(CF, ticks=lvls, format='%.4f')
plt.show()

我在 Windows 7 上使用 python 2.7.3 和 matplotlib 1.1.1。

【问题讨论】:

您的颜色条已有对数刻度。 @nordev - 我相信 OP 正在询问如何在颜色栏上设置刻度定位器和格式化程序以定期显示标签。 @JoeKington 啊,我似乎记得他的original question 中的 OP 希望将刻度线放置在数组lvls 中给定的值处,并以对数间距,但也许我只是误解了什么他的意思是。感谢您指出。 你可以用matplotlib.colors.LogNorm()做一些类似于this answer的事情 【参考方案1】:

我建议生成一个伪彩条如下(解释见cmets):

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.colors import LogNorm
import matplotlib.gridspec as gridspec

delta = 0.025

x = y = np.arange(0, 3.01, delta)
X, Y = np.meshgrid(x, y)
Z1 = plt.mlab.bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0)
Z2 = plt.mlab.bivariate_normal(X, Y, 1.5, 0.5, 1, 1)
Z = 1e6 * (Z1 * Z2)

fig=plt.figure()

#
# define 2 subplots, using gridspec to control the 
# width ratios:
#
# note: you have to import matplotlib.gridspec for this
#
gs = gridspec.GridSpec(1, 2,width_ratios=[15,1])

# the 1st subplot
ax1 = plt.subplot(gs[0])

lvls = np.logspace(0,4,20)

CF = ax1.contourf(X,Y,Z,
                  norm = LogNorm(),
                  levels = lvls
                 )
CS = ax1.contour(X,Y,Z,
                 norm = LogNorm(),
                 colors = 'k',
                 levels = lvls
                )

#
# the pseudo-colorbar
#

# the 2nd subplot
ax2 = plt.subplot(gs[1])        

#
# new levels!
#
# np.logspace gives you logarithmically spaced levels - 
# this, however, is not what you want in your colorbar
#
# you want equally spaced labels for each exponential group:
#
levls = np.linspace(1,10,10)
levls = np.concatenate((levls[:-1],np.linspace(10,100,10)))
levls = np.concatenate((levls[:-1],np.linspace(100,1000,10)))
levls = np.concatenate((levls[:-1],np.linspace(1000,10000,10)))

#
# simple x,y setup for a contourf plot to serve as colorbar
#
XC = [np.zeros(len(levls)), np.ones(len(levls))]
YC = [levls, levls]
CM = ax2.contourf(XC,YC,YC, levels=levls, norm = LogNorm())
# log y-scale
ax2.set_yscale('log')  
# y-labels on the right
ax2.yaxis.tick_right()
# no x-ticks
ax2.set_xticks([])

plt.show()

这会给你一个这样的情节:

编辑

或者,在调用colorbar 时使用新级别和spacing='proportional' 选项:

    替换这一行:

    lvls = np.logspace(0,4,20)  
    

    这些:

    lvls = np.linspace(1,10,5)
    lvls = np.concatenate((lvls[:-1],np.linspace(10,100,5)))
    lvls = np.concatenate((lvls[:-1],np.linspace(100,1000,5)))
    lvls = np.concatenate((lvls[:-1],np.linspace(1000,10000,5)))
    

    替换这一行:

    cbar = plt.colorbar(CF, ticks=lvls, format='%.4f')
    

    用这个:

    cbar = plt.colorbar(CF, ticks=lvls, format='%.2f', spacing='proportional')
    

你最终会得到这个情节:

(仅更改了format,因为新的刻度不需要 4 位小数)

编辑 2 如果你想像我使用的那样自动生成关卡,你可以考虑这段代码:

levels = []
LAST_EXP = 4
N_LEVELS = 5
for E in range(0,LAST_EXP):
    levels = np.concatenate((levels[:-1],np.linspace(10**E,10**(E+1),N_LEVELS)))

【讨论】:

以上是关于matplotlib 等高线图:对数刻度中的比例颜色条级别的主要内容,如果未能解决你的问题,请参考以下文章

通过matplotlib中的因子更改绘图比例

使用多个连接的箱线图更改 Matplotlib 中的轴刻度

Matplotlib 对数刻度刻度标签数字格式

Seaborn 线图对数刻度

Matplotlib:等高线图顶部的前景散点图

使用 matplotlib 的 2d 密度等高线图