При изучении дескрипторной графики в MATLAB обнаружилась нехватка «юзер френдли» функционала, а именно отсутствие стандартной команды позволяющей добавить дополнительную горизонтальную ось.

Добавление дополнительной вертикальной оси, командой plotyy предусмотрено и в help к ней, в разделе topics, есть пример добавления дополнительной оси x, однако данный пример, как и сама команда, не без недостатков, что любезно сообщает нам сам разработчик фразой:
plotyy is not recommended

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

  • Во-первых, нам предлагают расположить дополнительную ось в самой что ни на есть моветоновой области — в верху графика. Глаза разбегаются при попытке анализа такой картины...
  • Во-вторых, как подписывать такую ось даже продвинутому пользователю matlab может быть не ясно;
  • В-третьих, зачем нам ещё одна ось y?

Код из help
figure
x1 = 0:0.1:40;
y1 = 4.*cos(x1)./(x1+2);
line(x1,y1,'Color','r')
title('Не читаемо') % Сам вставил
ax1 = gca; % current axes
ax1.XColor = 'r';
ax1.YColor = 'r';
ax1_pos = ax1.Position; % position of first axes
ax2 = axes('Position',ax1_pos,...
    'XAxisLocation','top',...
    'YAxisLocation','right',...
    'Color','none');
x2 = 1:0.2:20;
y2 = x2.^2./x2.^3;
line(x2,y2,'Parent',ax2,'Color','k')
xlabel('f,Гц') % Сам вставил


Визуализированно распекаю пример из help
image

Для решения выше указанных проблем напишем свой код:

Решение проблем
clc
clear all
close all
%% Мои данные, возьми свои
U=[5.5 5.5 5.5 5.2 5.1 5 5 4.8 4.8]; % Значения амплитуды
F=[30 40 50 10000 12000 14000 16000 18000 20000]; % Значения частоты
[xi,ni]=find(F==50);
K=U/U(ni); % Расчёт относительных значений АЧХ
%%
figure
%% Это устанавливает шрифт и размер, речь не об этом
set(0,'DefaultAxesFontSize',20,'DefaultAxesFontName','Times New Roman');
set(0,'DefaultTextFontSize',20,'DefaultTextFontName','Times New Roman');
%% То, о чём шла речь
ax=get(axes,'Position'); % Получаю стандартное расположение осей в виде числового массива
a=gca; % Получаю свойства стандартных осей
set(a,'Position',[ax(1) ax(2)+(ax(2)/2) ax(3) ax(4)-ax(4)/10]) % Сдвигаю стандартные оси
plot(a,log(F),K,'-o'); % Строю свой график
xlim(a,[min(log(F)) max(log(F))]) % Задаю пределы своих осей
grid on % Сетка
BX=get(gca,'XTick'); % Получаю стандартную градуировку оси x в виде числового массива
BY=get(gca,'YTick'); % Получаю стандартную градуировку оси y в виде числового массива
%% Подписываю первые оси используя сдвиг
xlabel('бел','Position',[BX(size(BX,2))+1.1 BY(1)+(BY(1)/100)]) 
ylabel('K(f)')
%% Строю и подписываю дополнительную горизонтальную ось
F1=num2str(F,'%0.0i\n'); % Перевожу отсчёты предназначенные для дополнительной оси в строковый формат
ax2=[ax(1) ax(2)-(ax(2)/4) ax(3) 0]; % Задаю сдвиг относительно первых осей
b=axes('Position',ax2); % Ввожу сдвиг
xlabel('f, Гц', 'Position',[BX(size(BX,2))+1.1 BY(1)+(BY(1)/100)]) % Подписываю вторую ось
xlim(b,[min(log(F)) max(log(F))]) % Задаю пределы дополнительной оси, учитывая сдвиг
xticks(b,log(F)) % Градуирую дополнительную ось
xticklabels(b,F1) % Подписываю дополнительную ось
xtickangle(90) % Поворачиваю подпись дополнительной оси, для удобства восприятия


Давайте подробней рассмотрим некоторые элементы кода:

С помощью ниже указанной команды получаем положение осей в виде числового массива.

ax=get(axes,'Position');

Массив ax представлен в виде [a b c d], где a и b — положение левого нижнего угла графика, по горизонтали и по вертикали соответственно. Т. е. координаты начала отсчёта; с — длина горизонтальной оси, d — длина вертикальной оси.

Вводя смещения ни какое золотое сечение не вычислялось, всё «на глаз»:

set(a,'Position',[ax(1) ax(2)+(ax(2)/2) ax(3) ax(4)-ax(4)/10]) 

Так, ax(2)+(ax(2)/2) — смещает начало стандартной оси по вертикали в половину текущего, т. е. вверх от первоначального положения, что необходимо для удобочитаемости нумерованных отметок шкалы. Смещение ax(4)-ax(4)/10 задаёт размер первых осей по вертикали, т.е. уменьшает на десятую часть от текущего значения, нужно для удобочитаемости подписи графика, напомню title. Если задать d=0, то вертикальной оси попросту будет не будет видно, чем и воспользуемся в случае:

ax2=[ax(1) ax(2)-(ax(2)/4) ax(3) 0]; 

Следующий код позволяет задать положение подписей горизонтальных осей:

BX=get(gca,'XTick'); 
BY=get(gca,'YTick'); 
xlabel('бел','Position',[BX(size(BX,2))+1.1 BY(1)+(BY(1)/100)]) 
xlabel('f, Гц', 'Position',[BX(size(BX,2))+1.1 BY(1)+(BY(1)/100)]) 

Массив BX, равно как и BY, представлен как [x y], где x — положение подписи по горизонтали, y — положение подписи по вертикали.

В результате мы можем лицезреть вот такую красоту
image

Ниже оставлю пару полезных ссылок.

описание команды axes;
настройки команды axes;
команда plotyy;
метод введения дополнительной горизонтальной оси от разработчиков.

Комментарии (5)


  1. Dubus
    10.03.2018 19:48

    Не в обиду тем, кто пользуется этим продуктом в проф. сфере, но, ощущение такое, будто эти программы пишут инопланетяне для других инопланетян в соседней галактике.


    1. novikovag
      11.03.2018 14:43

      Они просто математики.


  1. mickvav
    11.03.2018 15:01

    Ну, не знаю, чем вам не понравились подписи на разных сторонах графика. Вот у gnuplot-а это всё выглядит вполне естественно — gnuplot.sourceforge.net/demo/linkedaxes.html


    1. EliVarsh Автор
      11.03.2018 15:30

      Если график распечатан, например на листе A4, сложней сопоставлять оси находящиеся далеко друг от друга. Собственно пара осей, при условии что на второй график не строится, необходима для сопоставления величин.


  1. einhander
    12.03.2018 00:03

    В R такое делается буквально за пару-тройку строчек кода.