Как скрыть нулевые значения в графике bar3 в MATLAB

У меня есть двухмерная гистограмма (график 3D – несколько гистограмм, граффитированных бок о бок), которые я создал с помощью команды plot bar3. Однако все нулевые значения отображаются как плоские квадраты в плоскости ху. Есть ли способ предотвратить отображение 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) 

Как вы можете видеть, на графике имеется немало нулевых значений. Закрытие фигуры и повторное построение после замены нhive 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 

И вот иллюстрация (с обязательными свободными кругами):

введите описание изображения здесь

Как это работает…

Если ваш вектор подсчета bin равен N-by-1 , тогда bar3 будет bar3 прямоугольные заплатки 6*N (то есть 6 граней кубоида для каждого бункера). Таким 'ZData' свойство 'ZData' для каждого набора объектов патча в h будет (6*N)-by-4 , так как для каждой прямоугольной грани есть 4 угла. Таким образом, каждый кластер из 6 строк свойства 'ZData' представляет собой набор z-координат для 6 граней одного бина.

Вышеприведенный код сначала создает логический вектор с единицами, каждый из которых имеет значение 0, затем каждый раз этот элемент 6 раз реплицирует с помощью функции kron . Это становится индексом для строк свойства 'ZData' , и этот индекс используется для установки z-координат в nan для патчей пустых бункеров. Это приведет к тому, что патчи не будут отображаться.


РЕДАКТИРОВАТЬ:

Вот немного модифицированная версия кода, которая делает ее более общей, выбирая высоту 'ZData' из свойства '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 

Вот пример, который показывает, как скрыть столбцы с нулевыми значениями. Мы начинаем с нормального участка BAR3 :

 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 

после

Объяснение:

Для каждой группы баров создается surface графический объект (с дескриптором, хранящимся в h(i) ). Это Z-координатная matrix. ZData представляется как matrix 6*N-by-4 (то же самое для XData , YData и CData ), где N – количество прямоугольных баров в каждой группе или 7 в приведенном выше примере.

Таким образом, каждый прямоугольник представлен 6×4 matrixми (по одному для каждой из координат 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) 

rectangle_surface

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

Все такие матрицы объединены как одна высокая matrix, а прямоугольники все рисуются с использованием одного поверхностного объекта. Это достигается за счет использования значений NaN для разделения разных частей, как внутри точек одного и того же прямоугольника, так и между разностными прямоугольниками.

Итак, что делает вышеприведенный код, это искать прямоугольники, где Z-высота равна нулю, и заменить все свои значения значениями 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 

Благодаря!

Давайте будем гением компьютера.