2013-11-26 3 views
8

Я пытаюсь создать полярную диаграмму с matplotlib и python 2.7, но я изо всех сил пытаюсь увеличить пространство между X-Axis и Tick Labels для этой же оси. Как вы можете видеть на картинке, ярлыки для 12:00 и 6:00 выглядят просто отлично, я желаю того же места для всех других ярлыков.python + matplotlib: как вставить больше места между осью и отметками тика в полярной диаграмме?

Я попытался с

ax.xaxis.LABELPAD = 10 

но это не имеет никакого эффекта.

enter image description here

Вот мой код (извините за беспорядок ....):

import numpy as np 
import matplotlib as mpl 
mpl.use('Agg') 
import matplotlib.pyplot as plt 
import matplotlib.dates 
from matplotlib.dates import YearLocator, MonthLocator, DateFormatter 
import matplotlib.cm as cm 
import matplotlib.ticker as tkr 
import pdb 
def plot_clock(data,filename,path,**kwargs): # (x,y,colors,lab_x,lab_y,xTicks,filename,legend,**kwargs): 
    bins = [0,0.5,1.5,2.5,3.5,4.5,5.5,6.5,7.5,8.5,9.5,10.5,11.5,12,12.5,13.5,14.5,15.5,16.5,17.5,18.5,19.5,20.5,21.5,22.5,23.5,23.999999]; 
    data = np.array(data)/(60*60) 
    DATA_ = np.histogram(data,bins)[0] 
    def hour_formatAM(x, p): 
     #pdb.set_trace() 
     if x > 0: 
      return str(format(x*6/np.pi, "01.0f") + ':00') 
     else: 
      return '12:00' 

    def hour_formatPM(x, p): 
     #pdb.set_trace() 
     if x > 0: 
      return str(format(x*6/np.pi+12, "01.0f") + ':00') 
     else: 
      return '24:00' 

    '''font = {'family' : 'normal', 
     'weight' : 'bold', 
     'size' : 12} 
    mpl.rc('font', **font)''' 

    mpl.rcParams.update({'font.size': 8}) 
    #sub plot AM 
    theta = np.array(bins[1:13]) * np.pi/6 
    radii = DATA_[1:13] 
    radii[-1] += DATA_[0] 
    width = 1 * np.pi/6 

    fig = plt.figure(figsize=(5.5,3),dpi=600) 
    ax = fig.add_subplot(121, polar=True) 
    bars = ax.bar(theta, radii, width=width, bottom=0) 
    ax.set_theta_offset(np.pi/2) 
    ax.set_theta_direction(-1) 

    ax.xaxis.set_ticks(np.arange(0, np.pi*2, np.pi/6)) 
    ax.get_xaxis().set_major_formatter(tkr.FuncFormatter(hour_formatAM)) 
    ax.yaxis.set_ticks(np.arange(1,max(DATA_),1)) 
    for t, bar in zip(theta, bars): 
     bar.set_facecolor(plt.cm.jet(t/12.)) 
     bar.set_alpha(0.5) 


    #sub plot PM 
    theta = np.array(bins[14:26]) * np.pi/6 
    radii = DATA_[14:26] 
    radii[-1] += DATA_[13] 
    width = 1 * np.pi/6 

    ax = fig.add_subplot(122, polar=True) 
    bars = ax.bar(theta, radii, width=width, bottom=0) 
    ax.set_theta_offset(np.pi/2) 
    ax.set_theta_direction(-1) 
    pdb.set_trace() 
    ax.xaxis.set_ticks(np.arange(0, np.pi*2, np.pi/6)) 
    ax.get_xaxis().set_major_formatter(tkr.FuncFormatter(hour_formatPM)) 
    ax.yaxis.set_ticks(np.arange(1,max(DATA_),1)) 
    for t, bar in zip(theta, bars): 
     bar.set_facecolor(plt.cm.jet(t/12.)) 
     bar.set_alpha(0.5) 
    #pdb.set_trace() 
    #fig.tight_layout() 
    #xlabels = [item.get_text() for item in ax.get_xticklabels()] 
    ax.xaxis.LABELPAD = 10 
    #[item.set_fontsize(12) for item in ax.xaxis.get_major_ticks()] 

    fig.subplots_adjust(wspace = 0.4) # http://matplotlib.org/faq/howto_faq.html 
    fig.savefig(path + filename,format='pdf') 


data = [ 10.49531611, 22.49511583, 10.90891806, 18.99525417, 
     21.57165972, 6.687755 , 6.52137028, 15.86534639, 
     18.53823556, 6.32563583, 12.99365833, 11.06817056, 
     17.29261306, 15.31288556, 19.16236667, 10.38483333, 
     14.51442222, 17.01413611, 6.96102278, 15.98508611, 
     16.5287 , 15.26533889, 20.83520278, 17.21952056, 
     7.3225775 , 16.42534361, 14.38649722, 21.63573111, 16.19249444] 
data = np.array(data)*60*60 
plot_clock(data,'figure2_StartTime.pdf','./') 
+3

Это может быть полезна: HTTP: // StackOverflow .com/questions/17159668/matplotlib-add-padding-offset-to-polar-plot-tick-labels – dabillox

+1

Спасибо, это действительно помогло. с 'ax.set_thetagrids (thetaticks, frac = 1.2)' Я могу исправить ошибку заполнения, но он будет заполнять все тики, также 12:00 и 6:00, которые выглядят хорошо, как сейчас. – otmezger

+0

Если вы хотите настроить на основе каждой метки, вам либо придется сделать это вручную, либо написать код, чтобы проверить, перекрывает ли область ограничения текста ось. – tacaswell

ответ

7

@dabillox уже упоминалось, используя frac kwarg к ax.set_thetagrids.

Однако, как вы заметили, то, что вы действительно хотите изменить, - это выравнивание меток, а не общее смещение метки ярлыков.

На стороне записки, причина того, что labelpad не имела никакого эффекта является то, что он контролирует прокладку между этикеткой осей (например, plt.xlabel, plt.ylabel) и осью, а не клещ этикеткой.

Прежде всего, вы можете написать свой примерный код немного более чисто. Вот более или менее, как я бы подойти, что вы делаете (обратите внимание, что это будет по-прежнему имеют те же проблемы с позиционированием клещ ярлык):

import numpy as np 
import matplotlib.pyplot as plt 
import matplotlib.ticker as tkr 

def main(): 
    data = [ 10.49531611, 22.49511583, 10.90891806, 18.99525417, 
      21.57165972, 6.687755 , 6.52137028, 15.86534639, 
      18.53823556, 6.32563583, 12.99365833, 11.06817056, 
      17.29261306, 15.31288556, 19.16236667, 10.38483333, 
      14.51442222, 17.01413611, 6.96102278, 15.98508611, 
      16.5287 , 15.26533889, 20.83520278, 17.21952056, 
      7.3225775 , 16.42534361, 14.38649722, 21.63573111, 16.19249444] 
    data = np.array(data)*60*60 
    plot_clock(data) 
    plt.show() 

def plot_clock(data): 
    def hour_formatAM(x, p): 
     hour = x * 6/np.pi 
     return '{:0.0f}:00'.format(hour) if x > 0 else '12:00' 

    def hour_formatPM(x, p): 
     hour = x * 6/np.pi 
     return '{:0.0f}:00'.format(hour + 12) if x > 0 else '24:00' 

    def plot(ax, theta, counts, formatter): 
     colors = plt.cm.jet(theta/12.0) 
     ax.bar(theta, counts, width=np.pi/6, color=colors, alpha=0.5) 
     ax.xaxis.set_major_formatter(tkr.FuncFormatter(formatter)) 

    plt.rcParams['font.size'] = 8 

    bins = np.r_[0, 0.5:12, 12, 12.5:24, 23.99999] 
    data = np.array(data)/(60*60) 
    counts = np.histogram(data,bins)[0] 

    counts[13] += counts[0] 
    counts[-1] += counts[13] 

    fig, axes = plt.subplots(ncols=2, figsize=(5.5, 3), dpi=200, 
          subplot_kw=dict(projection='polar')) 
    fig.subplots_adjust(wspace=0.4) 
    for ax in axes: 
     ax.set(theta_offset=np.pi/2, theta_direction=-1, 
       xticks=np.arange(0, np.pi*2, np.pi/6), 
       yticks=np.arange(1, counts.max())) 

    plot(axes[0], bins[1:13] * np.pi/6, counts[1:13], hour_formatAM) 
    plot(axes[1], bins[14:26] * np.pi/6, counts[14:26], hour_formatPM) 

main() 

enter image description here


Если мы хотим избежать неправильных выровнены клеща меток, мы можем установить горизонтальное выравнивание в зависимости от их положения:

import numpy as np 
import matplotlib.pyplot as plt 
import matplotlib.ticker as tkr 

def main(): 
    data = [ 10.49531611, 22.49511583, 10.90891806, 18.99525417, 
      21.57165972, 6.687755 , 6.52137028, 15.86534639, 
      18.53823556, 6.32563583, 12.99365833, 11.06817056, 
      17.29261306, 15.31288556, 19.16236667, 10.38483333, 
      14.51442222, 17.01413611, 6.96102278, 15.98508611, 
      16.5287 , 15.26533889, 20.83520278, 17.21952056, 
      7.3225775 , 16.42534361, 14.38649722, 21.63573111, 16.19249444] 
    data = np.array(data)*60*60 
    axes = plot_clock(data) 
    for ax in axes: 
     realign_polar_xticks(ax) 
    plt.show() 

def realign_polar_xticks(ax): 
    for x, label in zip(ax.get_xticks(), ax.get_xticklabels()): 
     if np.sin(x) > 0.1: 
      label.set_horizontalalignment('left') 
     if np.sin(x) < -0.1: 
      label.set_horizontalalignment('right') 

def plot_clock(data): 
    def hour_formatAM(x, p): 
     hour = x * 6/np.pi 
     return '{:0.0f}:00'.format(hour) if x > 0 else '12:00' 

    def hour_formatPM(x, p): 
     hour = x * 6/np.pi 
     return '{:0.0f}:00'.format(hour + 12) if x > 0 else '24:00' 

    def plot(ax, theta, counts, formatter): 
     colors = plt.cm.jet(theta/12.0) 
     ax.bar(theta, counts, width=np.pi/6, color=colors, alpha=0.5) 
     ax.xaxis.set_major_formatter(tkr.FuncFormatter(formatter)) 

    plt.rcParams['font.size'] = 8 

    bins = np.r_[0, 0.5:12, 12, 12.5:24, 23.99999] 
    data = np.array(data)/(60*60) 
    counts = np.histogram(data,bins)[0] 

    counts[13] += counts[0] 
    counts[-1] += counts[13] 

    fig, axes = plt.subplots(ncols=2, figsize=(5.5, 3), dpi=200, 
          subplot_kw=dict(projection='polar')) 
    fig.subplots_adjust(wspace=0.5) 

    for ax in axes: 
     ax.set(theta_offset=np.pi/2, theta_direction=-1, 
       xticks=np.arange(0, np.pi*2, np.pi/6), 
       yticks=np.arange(1, counts.max())) 

    plot(axes[0], bins[1:13] * np.pi/6, counts[1:13], hour_formatAM) 
    plot(axes[1], bins[14:26] * np.pi/6, counts[14:26], hour_formatPM) 
    return axes 

main() 

enter image description here

И, наконец, если вы хотите сделать это «правильно», независимо от направления тета и смещение, сделать что-то вроде:

def realign_polar_xticks(ax): 
    for theta, label in zip(ax.get_xticks(), ax.get_xticklabels()): 
     theta = theta * ax.get_theta_direction() + ax.get_theta_offset() 
     theta = np.pi/2 - theta 
     y, x = np.cos(theta), np.sin(theta) 
     if x >= 0.1: 
      label.set_horizontalalignment('left') 
     if x <= -0.1: 
      label.set_horizontalalignment('right') 
     if y >= 0.5: 
      label.set_verticalalignment('bottom') 
     if y <= -0.5: 
      label.set_verticalalignment('top') 

enter image description here

 Смежные вопросы

  • Нет связанных вопросов^_^