2011-10-07 5 views
2

Я пытаюсь сделать 2D-график плотности (из некоторых данных моделирования) с помощью matplotlib. Мои данные x и y определяются как log10 некоторых величин. Как я могу получить логарифмические оси (с лог-малыми тиками)?Как получить оси журнала для графика плотности с помощью matplotlib?

Вот Exemple моего кода:

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. 
Смежные вопросы