Как скрыть нулевые значения на графике bar3 в MATLAB
-
20-09-2019 - |
Вопрос
У меня есть двумерная гистограмма (график 3D - несколько гистограмм, построенных бок о бок), которую я сгенерировал с помощью команды bar3 plot.Однако все нулевые значения отображаются в виде плоских квадратов в плоскости x-y.Есть ли способ, которым я могу запретить MATLAB отображать значения?Я уже пробовал заменить все нули на NANS, но это ничего не изменило в сюжете.Вот код, с которым я экспериментировал:
x1=normrnd(50,15,100,1); %generate random data to test code
x2=normrnd(40,13,100,1);
x3=normrnd(65,12,100,1);
low=min([x1;x2;x3]);
high=max([x1;x2;x3]);
y=linspace(low,high,(high-low)/4); %establish consistent bins for histogram
z1=hist(x1,y);
z2=hist(x2,y);
z3=hist(x3,y);
z=[z1;z2;z3]';
bar3(z)
Как вы можете видеть, на графике довольно много нулевых значений.Закрытие рисунка и повторное построение графика после замены нулей на NANS, похоже, ничего не меняет:
close
z(z==0)=NaN;
bar3(z)
Решение
Одним из решений является изменение графических объектов, созданных bar3
.Во-первых, вы должны получить дескрипторы, возвращенные из bar3
:
h = bar3(z);
В вашем случае, h
будет 3-элементный вектор маркеров, по одному для каждого набора цветных полос.Затем следующий код должен сделать ячейки с нулевым количеством невидимыми:
for i = 1:numel(h)
index = logical(kron(z(:, i) == 0, ones(6, 1)));
zData = get(h(i), 'ZData');
zData(index, :) = nan;
set(h(i), 'ZData', zData);
end
А вот иллюстрация (с обязательными кругами свободной руки):
Как это работает...
Если ваш вектор количества ячеек равен N-by-1
, тогда bar3
будет заговор 6*N
прямоугольные заплаты (т.е.6 граней кубоида для каждой ячейки).В 'ZData'
свойство для каждого набора объектов исправления в h
следовательно, будет (6*N)-by-4
, поскольку для каждой прямоугольной грани имеется 4 угла.Каждый кластер из 6 рядов 'ZData'
таким образом, свойство представляет собой набор z-координат для 6 граней одной ячейки.
Приведенный выше код сначала создает логический вектор с единицами везде, где количество ячеек равно 0, затем реплицирует каждый элемент этого вектора 6 раз, используя kron
функция.Это становится индексом для строк 'ZData'
свойство, и этот индекс используется для установки z-координат в nan
для участков с пустыми мусорными баками.Это приведет к тому, что исправления не будут отрисованы.
Редактировать:
Вот слегка измененная версия кода, которая делает его более общим, извлекая высоту полосы из 'ZData'
свойство из построенных столбцов, так что все, что нужно для его работы, - это дескрипторы, возвращенные из bar3
.Я также заключил код в функцию (без ошибок и проверки входных данных).:
function remove_empty_bars(hBars)
for iSeries = 1:numel(hBars)
zData = get(hBars(iSeries), 'ZData'); % Get the z data
index = logical(kron(zData(2:6:end, 2) == 0, ones(6, 1))); % Find empty bars
zData(index, :) = nan; % Set the z data for empty bars to nan
set(hBars(iSeries), 'ZData', zData); % Update the graphics objects
end
end
Другие советы
Вот пример, который показывает, как скрыть столбцы с нулевыми значениями.Мы начинаем с обычного БАР3 сюжет:
x = 1:7;
Y = jet(numel(x));
h = bar3(x,Y,'detached');
xlabel x; ylabel y; zlabel z; box on;
Обратите внимание, что переменная h
содержит массив surface
маркеры (в данном случае 3, по одному для каждой "группы" стержней.Группы соответствуют столбцам Y
матрицы, каждая из которых представлена другим цветом).
А теперь код для скрытия нулевых значений:
for i=1:numel(h)
%# get the ZData matrix of the current group
Z = get(h(i), 'ZData');
%# row-indices of Z matrix. Columns correspond to each rectangular bar
rowsInd = reshape(1:size(Z,1), 6,[]);
%# find bars with zero height
barsIdx = all([Z(2:6:end,2:3) Z(3:6:end,2:3)]==0, 2);
%# replace their values with NaN for those bars
Z(rowsInd(:,barsIdx),:) = NaN;
%# update the ZData
set(h(i), 'ZData',Z)
end
Объяснение:
Для каждой группы стержней, a surface
графический объект создан (с дескриптором, сохраненным в h(i)
).Это матрица Z-координат ZData
представляется в виде 6*N-by-4
матрица (то же самое для XData
, YData
, и CData
матрицы), где N - количество прямоугольных стержней в каждой группе или 7 в приведенном выше примере.
Таким образом, каждый прямоугольник представлен матрицами 6x4 (по одной для каждой из координат X / Y / Z).Например, координаты одного такого прямоугольника будут выглядеть следующим образом:
>> xx = get(h(3),'XData'); yy = get(h(3),'YData'); zz = get(h(3),'ZData');
>> xx(1:6,:)
ans =
NaN 2.6 3.4 NaN
2.6 2.6 3.4 3.4
2.6 2.6 3.4 3.4
NaN 2.6 3.4 NaN
NaN 2.6 3.4 NaN
NaN NaN NaN NaN
>> yy(1:6,:)
ans =
NaN 0.6 0.6 NaN
0.6 0.6 0.6 0.6
1.4 1.4 1.4 1.4
NaN 1.4 1.4 NaN
NaN 0.6 0.6 NaN
NaN NaN NaN NaN
>> zz(1:6,:)
ans =
NaN 0 0 NaN
0 1 1 0
0 1 1 0
NaN 0 0 NaN
NaN 0 0 NaN
NaN NaN NaN NaN
Во втором столбце каждого из них прослеживаются точки вдоль левой грани, в третьем столбце прослеживаются точки вдоль правой грани, и когда они будут соединены, будут нарисованы 4 грани прямоугольника:
>> surface(xx(1:6,2:3), yy(1:6,2:3), zz(1:6,2:3), cc(1:6,2:3))
>> view(3)
Первый и последний столбцы нарисуют две оставшиеся грани, закрыв стороны прямоугольника.
Все такие матрицы объединяются в одну матрицу высоты, и все прямоугольники рисуются с использованием одного объекта surface.Это достигается за счет использования NaN
значения для разделения различных частей, как внутри точек одного и того же прямоугольника, так и между разными прямоугольниками.
Итак, что делает приведенный выше код, так это ищет прямоугольники, где Z-height равна нулю, и заменяет все его значения на NaN
значения, которые эффективно указывают MATLAB не рисовать поверхности, образованные этими точками.
Моей проблемой были не нулевые значения, а значения NaN (которые преобразуются в нулевые значения внутри bar3).Я хотел продолжать отображать элементы со значениями ноль, но не элементы со значением nan.Я немного подкорректировал код, и он сработал безукоризненно:
for i = 1:numel(h)
index = logical(kron(isnan(z(:,i)),ones(6,1)));
zData = get(h(i),'ZData');
zData(index,:) = nan;
set(h(i),'ZData',zData);
end
Спасибо!