делая увеличенный график для половины оси x [дубликат]

Принятый ответ работает, но немного больше объяснений не повредит.

Атрибуты класса не становятся атрибутами экземпляра при создании экземпляра. Они становятся атрибутами экземпляра, когда им присваивается значение.

В исходном коде значение no присваивается атрибуту list после создания экземпляра; поэтому он остается атрибутом класса. Определение списка внутри __init__ работает, потому что __init__ вызывается после создания экземпляра. В качестве альтернативы, этот код также выдаст желаемый результат:

>>> class a:
    list = []

>>> y = a()
>>> x = a()
>>> x.list = []
>>> y.list = []
>>> x.list.append(1)
>>> y.list.append(2)
>>> x.list.append(3)
>>> y.list.append(4)
>>> print(x.list)
[1, 3]
>>> print(y.list)
[2, 4]

Однако запутанный сценарий в вопросе никогда не случится с неизменяемыми объектами, такими как числа и строки, поскольку их значение не может быть изменено без назначения. Например, код, аналогичный оригиналу со строковым атрибутом, работает без каких-либо проблем:

>>> class a:
    string = ''


>>> x = a()
>>> y = a()
>>> x.string += 'x'
>>> y.string += 'y'
>>> x.string
'x'
>>> y.string
'y'

Итак, чтобы суммировать: атрибуты класса становятся атрибутами экземпляра тогда и только тогда, когда им присваивается значение после создания, в методе __init__ или нет. Это хорошо, потому что таким образом вы можете иметь статические атрибуты, если никогда не присваиваете значение атрибуту после создания экземпляра.

1
задан JadeChee 22 July 2015 в 21:12
поделиться

2 ответа

Это пример, показывающий, как я это сделал, разместив три оси вручную на фигуре.

from __future__ import division, unicode_literals
import matplotlib.pyplot as plt
import numpy as np

plt.close('all')

# ----- PREPARE DATA ----

t = np.arange(0, 7 * 10**5, 10)
x = np.abs(np.sin(t/10.**2)) * 300

# ----- FIG CREATION ----

fig = plt.figure(figsize=(8, 5), facecolor='white')

# Margins (dimensions are in inches):
left_margin = 0.6 / fig.get_figwidth()
right_margin = 0.25 / fig.get_figwidth()
bottom_margin = 0.75 / fig.get_figheight()
top_margin = 0.25 / fig.get_figwidth()
mid_margin = 0.1 / fig.get_figwidth()  # horizontal space between subplots

# ----- DEFINE PARAMETERS FOR EACH AXE ----

# Proportion of the figure's width taken by each axe (the sum must == 1):
f = [0.5, 0.3, 0.2]

xmin = [200, 50, 0]     # xaxis minimum values for each axe
xmax = [8200, 200, 50]  # xaxis maximum values for each axe
xscl = [2000, 50, 10]   # xaxis scale for each axe

ymin, ymax = 0, 320  # yaxis minimum and maximum values

colors = ['green', 'blue', 'red']  # colors of each plot
labels = ['label1', 'label2', 'label3']  # labels of each plot for the legend

Naxes = len(f)  # Total number of axes to add to the figure.

x0, y0 = left_margin, bottom_margin   # origin point of the axe
h = 1 - (bottom_margin + top_margin)  # height of the axe

# total width of the axes:
wtot = 1 - (left_margin + right_margin + (Naxes-1)*mid_margin)

lines = []  # to store handles for generating the legend later on
for i in range(Naxes):

    # ----- AXES CREATION ----

    w = wtot*f[i]  # width of the current axe
    ax = fig.add_axes([x0, y0, w, h], frameon=True, axisbg='none')

    if i == 0:  # First axe to the left
        ax.spines['right'].set_visible(False)
        ax.tick_params(right='off', labelright='off')

    elif i == Naxes-1:  # Last axe to the right
        ax.spines['left'].set_visible(False)
        ax.tick_params(left='off', labelleft='off',
                       right='off', labelright='off')
    else:
        ax.spines['left'].set_visible(False)
        ax.spines['right'].set_visible(False)
        ax.tick_params(left='off', labelleft='off',
                       right='off', labelright='off')

    # origin point of the next axe to be added to the figure:
    x0 += w + mid_margin

    # ----- SETUP XTICKS ----

    if i == Naxes-1:
        xticks = np.arange(xmin[i], xmax[i] + xscl[i]/2, xscl[i])
    else:
        xticks = np.arange(xmin[i]+xscl[i], xmax[i] + xscl[i]/2, xscl[i])
    ax.set_xticks(xticks)
    ax.xaxis.set_ticks_position('bottom')
    ax.tick_params(axis='x', direction='out', labelsize=8)

    xticks_minor = np.arange(xmin[i], xmax[i] + xscl[i]/5., xscl[i] / 5.)
    ax.set_xticks(xticks_minor, minor=True)
    ax.tick_params(axis='x', which='minor', direction='out')

    # ----- PLOT DATA ----

    line, = ax.plot(t, x, color=colors[i])
    lines.append(line)  # for plotting the legend

    ax.axis([xmin[i], xmax[i], ymin, ymax])
    ax.invert_xaxis()

# ---- SET XAXIS LABEL ----

fig.axes[0].set_xlabel('Time (years)', fontsize=12, va='bottom', ha='center')
fig.axes[0].xaxis.set_label_coords(0.5, 0.05, transform=fig.transFigure)

# -----  LEGEND ----

fig.axes[0].legend(lines, labels, loc=(0.1, 0.1), ncol=1, fancybox=True,
                   fontsize=12)

# ----- SHOW FIG ----

fig.savefig('SingleAxeThreeScale.png')
plt.show()

В результате:

4
ответ дан Jean-Sébastien 24 August 2018 в 18:58
поделиться

Проблема 1

Вы неправильно вызываете plt.subplots. Вот пример использования по умолчанию

(nrows = 1, ncols = 1, sharex = False, sharey = False, squeeze = True, subplot_kw = None, gridspec_kw = None, ** fig_kw)

Кажется, что вы хотите 5 подзаговоров в строке, поэтому установите nrows=1 и ncols=5

fig,axs = plt.subplots(nrows=1,ncols=5,sharey=True)
ax, ax2, ax3, ax4, ax5  = axs

Проблема 2

Вы необходимо правильно установить шипы - вы хотите, чтобы слева и справа были видны. Это легко сделать с помощью функции:

def multi_spine_adj( axs):
    axs[0].spines['right'].set_visible(False)
    axs[0].yaxis.tick_left()
    for ax in axs[1:-1]:
        ax.spines['right'].set_visible(False)
        ax.spines['left'].set_visible(False)
    axs[-1].spines['left'].set_visible(False)
    axs[-1].yaxis.tick_right()

#wvln0 = np.linspace( 0,5,50) # make some fake data
#alb0 =  np.random.random(50) #make some fake data 

opts = {'linestyle':'-', 'marker':'o', 'color':'r','linewidth':1,'label':'Haze = 0T'}

fig,axs = plt.subplots(1,5,sharey=True)

xlims = [(0.15,1.10),
        (1.15,2.25),
        (1.20,1.30),
        (1.55,1.65),
        (1.95,2.15)]

for i,ax in enumerate(axs):
    x1,x2 = xlims[i]
    ax.plot(wvln0,alb0,**opts)
    ax.set_xlim(x1,x2)

multi_spine_adj(axs)    
plt.show()

Совет

Обратите внимание, как вы можете легко перебирать axs, это делает ваш код более чистым и простым в изменении ( если вы хотите добавить больше перерывов, например)

2
ответ дан dermen 24 August 2018 в 18:58
поделиться
Другие вопросы по тегам:

Похожие вопросы: