2011-10-07 22 views
2

我想用matplotlib製作2D密度圖(來自一些模擬數據)。我的x和y數據被定義爲一些數量的log10。我怎樣才能得到對數座標軸(記錄次要記號)?如何使用matplotlib獲取密度圖的日誌軸?

這裏是我的代碼爲例:

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') 

回答

3

非常感謝你的建議。

下面我加入我自己的解決方案。這幾乎不是「最低工作範例」,但我已經把我的腳本剝離了很多!

簡而言之,我使用imshow來繪製「圖像」(一個帶有對數框的二維直方圖),並刪除這些座標軸。然後,我繪製了第二個空的(透明的)繪圖,正好位於第一個繪圖的頂部,以便獲取日誌軸,因爲imshow似乎不允許它。如果你問我,這很複雜!

我的代碼可能是從最優據我是新來的python和matplotlib ...

順便說一句,我不爲兩個原因使用hexbin: 1)它是運行速度太慢非常大的數據文件,就像我擁有的​​那種。 2)在我使用的版本中,六邊形稍大,即它們重疊,導致不規則形狀和大小的「像素」。 另外,我希望能夠以文本格式將直方圖數據寫入文件。

#!/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() 
3

從matplotlib.pyplot.hist文檔字符串,它看起來像有一個「登錄」參數設置爲「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. 

還有一個pyplot.loglog函數用於在x和y軸上繪製日誌縮放圖。

1

@gcalmettes的答案指的是pyplot.hist。爲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) 

你有興趣在xscale參數:

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