简体   繁体   English

如何使用matplotlib获取密度图的对数轴?

[英]How to get log axes for a density plot with matplotlib?

I am trying to make a 2D density plot (from some simulation data) with matplotlib. 我试图用matplotlib制作2D密度图(来自一些模拟数据)。 My x and y data are defined as the log10 of some quantities. 我的x和y数据被定义为某些数量的log10。 How can I get logarithmic axes (with log minor ticks)? 如何获得对数轴(带有对数小刻度)?

Here is an exemple of my code: 这是我的代码的例子:

import numpy as np
import matplotlib.pyplot as plt

Data = np.genfromtxt("data") # A 2-column data file
x = np.log10(Data[:,0])
y = np.log10(Data[:,1])

xmin = x.min()
xmax = x.max()
ymin = y.min()
ymax = y.max()

fig = plt.figure()
ax = fig.add_subplot(111)

hist = ax.hexbin(x,y,bins='log', gridsize=(30,30), cmap=cm.Reds)
ax.axis([xmin, xmax, ymin, ymax])

plt.savefig('plot.pdf')

From the matplotlib.pyplot.hist docstring, it looks like there is a 'log' argument to set to 'True' if you want log scale on axis. 从matplotlib.pyplot.hist docstring看,如果你想在轴上使用对数刻度,看起来有一个'log'参数设置为'True'。

hist(x, bins=10, range=None, normed=False, cumulative=False,
     bottom=None, histtype='bar', align='mid',
     orientation='vertical', rwidth=None, log=False, **kwargs)

log:
If True, the histogram axis will be set to a log scale. If log is True and x is a 1D
array, empty bins will be filtered out and only the non-empty (n, bins, patches) will be
returned.

There is also a pyplot.loglog function to make a plot with log scaling on the x and y axis. 还有一个pyplot.loglog函数可以在x和y轴上创建具有对数缩放的绘图。

Thank you very much for suggestions. 非常感谢您的建议。

Below, I join my own solution. 下面,我加入我自己的解决方案。 It is hardly "a minimum working example" but I have already stripped my script quite a lot! 它几乎不是“最低限度的工作示例”,但我已经剥离了我的剧本很多!

In a nutshell, I used imshow to plot the "image" (a 2D histogram with log bins) and I remove the axes. 简而言之,我使用imshow绘制“图像”(带有日志箱的2D直方图)并删除轴。 Then, I draw a second, empty (and transparent), plot, exactly on top of the first plot just to get log axes as imshow doesn't seem to allow it. 然后,我绘制第二个空的(和透明的)绘图,正好在第一个绘图的顶部,只是为了获得日志轴,因为imshow似乎不允许它。 Quite complicated if you ask me! 如果你问我,那很复杂!

My code is probably far from optimal as I am new to python and matplotlib... 我的代码可能远非最佳,因为我是python和matplotlib的新手......

By the way, I don't use hexbin for two reasons: 1) It is too slow to run on very big data files like the kind I have. 顺便说一句,我不使用hexbin有两个原因:1)在我这样的非常大的数据文件上运行它太慢了。 2) With the version I use, the hexagons are slightly too large, ie they overlap, resulting in "pixels" of irregular shapes and sizes. 2)对于我使用的版本,六边形稍微过大,即它们重叠,导致不规则形状和尺寸的“像素”。 Also, I want to be able to write the histogram data into a file in text format. 此外,我希望能够将直方图数据写入文本格式的文件中。

#!/usr/bin/python

# How to get log axis with a 2D colormap (i.e. an "image") ??
#############################################################
#############################################################

import numpy as np
import matplotlib.cm as cm
import matplotlib.pyplot as plt
import math

# Data file containing 2D data in log-log coordinates.
# The format of the file is 3 columns : x y v
# where v is the value to plotted for coordinate (x,y)
# x and y are already log values
# For instance, this can be a 2D histogram with log bins.
input_file="histo2d.dat"

# Parameters to set space for the plot ("bounding box")
x1_bb, y1_bb, x2_bb, y2_bb = 0.125, 0.12, 0.8, 0.925

# Parameters to set space for colorbar
cb_fraction=0.15
cb_pad=0.05

# Return unique values from a sorted list, will be required later
def uniq(seq, idfun=None): 
    # order preserving
    if idfun is None:
        def idfun(x): return x
    seen = {}
    result = []
    for item in seq:
        marker = idfun(item)
        # in old Python versions:
        # if seen.has_key(marker)
        # but in new ones:
        if marker in seen: continue
        seen[marker] = 1
        result.append(item)
    return result

# Read data from file. The format of the file is 3 columns : x y v
# where v is the value to plotted for coordinate (x,y)

Data = np.genfromtxt(input_file)
x = Data[:,0]
y = Data[:,1]
v = Data[:,2]

# Determine x and y limits and resolution of data

x_uniq = np.array(uniq(np.sort(x)))
y_uniq = np.array(uniq(np.sort(y)))

x_resolution = x_uniq.size
y_resolution = y_uniq.size

x_interval_length = x_uniq[1]-x_uniq[0]
y_interval_length = y_uniq[1]-y_uniq[0]

xmin = x.min()
xmax = x.max()+0.5*x_interval_length
ymin = y.min()
ymax = y.max()+0.5*y_interval_length

# Reshape 1D data to turn it into a 2D "image"

v = v.reshape([x_resolution, y_resolution])
v = v[:,range(y_resolution-1,-1,-1)].transpose()

# Plot 2D "image" 
# ---------------

# I use imshow which only work with linear axes.
# We will have to change the axes later...

axis_lim=[xmin, xmax, ymin, ymax]

fig = plt.figure()
ax = fig.add_subplot(111)
extent = [xmin, xmax, ymin, ymax]
img = plt.imshow(v, extent=extent, interpolation='nearest', cmap=cm.Reds, aspect='auto')
ax.axis(axis_lim)

# Make space for the colorbar
x2_bb_eff = (x2_bb-(cb_fraction+cb_pad)*x1_bb)/(1.0-(cb_fraction+cb_pad))
ax.set_position([x1_bb, y1_bb, x2_bb_eff-x1_bb, y2_bb-y1_bb])
position = ax.get_position()

# Remove axis ticks so that we can put log ticks on top
ax.set_xticks([])
ax.set_yticks([])

# Add colorbar
cb = fig.colorbar(img,fraction=cb_fraction,pad=cb_pad)
cb.set_label('Value [unit]')

# Add logarithmic axes
# --------------------

# Empty plot on top of previous one. Only used to add log axes.
ax = fig.add_subplot(111,frameon=False)
ax.set_xscale('log')
ax.set_yscale('log')
plt.plot([])
ax.set_position([x1_bb, y1_bb, x2_bb-x1_bb, y2_bb-y1_bb])

axis_lim_log=map(lambda x: 10.**x, axis_lim)
ax.axis(axis_lim_log)

plt.grid(b=True, which='major', linewidth=1)
plt.ylabel('Some quantity [unit]')
plt.xlabel('Another quantity [unit]')

plt.show()

The answer from @gcalmettes refers to pyplot.hist . @gcalmettes的答案是指pyplot.hist The signature for pyplot.hexbin is a bit different: pyplot.hexbin的签名有点不同:

hexbin(x, y, C = None, gridsize = 100, bins = None,
             xscale = 'linear', yscale = 'linear',
             cmap=None, norm=None, vmin=None, vmax=None, alpha=None, linewidths=None,
             edgecolors='none', reduce_C_function = np.mean, mincnt=None, marginals=True,
             **kwargs)

You are interested on the xscale parameter: 您对xscale参数感兴趣:

*xscale*: [ 'linear' | 'log' ]
    Use a linear or log10 scale on the horizontal axis.

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM