matlab 3d bar-chart matlab-figure colormap

matlab - ¿Cómo establecer colores arbitrarios para las barras en un gráfico de barras 3D?



bar-chart matlab-figure (3)

La función bar3 devuelve un objeto de superficie , uno para cada grupo (es decir, uno para cada color), por lo que todas las barras en un grupo se trazan esencialmente como una superficie ''rota''. Esto se explica muy bien en esta respuesta , por lo que no lo repetiré aquí.

En cambio, llegaré a la solución para este problema específico. La propiedad relevante de la superficie es CData . Cuando creamos el gráfico de barras, cada CData la superficie se asigna con una matriz de algún tamaño (vamos a llegar a esto) que es todo igual a un valor. Un valor diferente para cada superficie. Así es como la figura en su conjunto traduce su mapa de color al color de los grupos.

Como se escribió anteriormente (y se elabora en la respuesta vinculada ), cada grupo está representado por una superficie, por lo que se necesita una matriz completa para definir el color en cada punto de la superficie. Lo primero que queremos hacer es obtener este tamaño de matriz:

Z = peaks(5); bar_h = bar3(Z); % we take only the first one, but they are all the same size: cdata_sz = size(bar_h(1).CData) cdata_sz = 30 4

CData siempre tiene 4 columnas (ver aquí por qué), y el número de filas siempre es 6 * cantidad de grupos. Esto se debe a que se necesitan 5 vértices para crear un rectángulo cerrado con un objeto de área (el último vértice es como el primero) y una línea para el espaciado entre las barras con NaN, por lo que se verán separados.

A continuación, tenemos que ampliar nuestro mapa de colores original (que es del mismo tamaño de Z ) para que encaje en CData de la manera correcta. Básicamente, solo queremos repetir el mismo valor para todos los vértices que pertenecen a la misma barra. Asumiendo que Z es también nuestra información de color (es decir, nosotros coloreamos por altura) hacemos:

z_color = repelem(Z,6,4)

Ahora tenemos que dividir nuestro z_color en diferentes celdas en el número de nuestros grupos. Cada celda contendrá los datos de coloración para un objeto de superficie:

z_color = mat2cell(z_color,cdata_sz(1),ones(1,size(Z,2))*cdata_sz(2));

Y finalmente, aplicamos los nuevos datos de color a la gráfica de barras:

set(bar_h,{''CData''},z_color.'')

Como beneficio adicional, si queremos eliminar todos los valores cero de nuestra barra, se puede hacer fácilmente configurándolos en NaN:

Z(abs(Z)<eps) = nan; C(isnan(Z)) = nan; % if we use a colormap C different from Z

Todo lo anterior podría reducirse a esta práctica función:

function bar_h = Cbar3(Z,C,b,y) % Z - The data % C - CData (if other then Z values) % b - Minimum absolute value to keep colored % y - y-axis values to order the data by if nargin<2, C = Z; end if nargin<3 || isempty(b), b = 0; end Z(abs(Z)<b) = nan; C(isnan(Z)) = nan; if nargin<4 bar_h = bar3(Z); else bar_h = bar3(y,Z); end cdata_sz = size(bar_h(1).CData); z_color = repelem(C,6,4); z_color = mat2cell(z_color,... cdata_sz(1),ones(1,size(Z,2))*cdata_sz(2)); set(bar_h,{''CData''},z_color.'') end

Ejemplo de uso:

subplot 121 Z = peaks(30); Cbar3(Z,Z,0.5); pbaspect auto shading flat % just to get a cleaner look title(''Cbar3 using height as color'') subplot 122 Cbar3(Z,rand(size(Z)),0.5); pbaspect auto shading flat % just to get a cleaner look title(''Cbar3 using random as color'')

Resultado:

Digamos que tengo una matriz Z con algunos valores, y quiero ilustrarlo trazando los valores en Z por altura. La primera solución viene a la mente es una superficie, pero el uso de surf y funciones similares con matrices pequeñas no se ve bien.

Así que pensé en usar algo así como un diagrama de barras 3D con bar3 . Pero el problema es que esta función siempre establece el color por el grupo y no por la altura, y no puedo lograr que lo haga.

Aquí hay un ejemplo:

Z = peaks(5); subplot 121 surf(Z) title(''Surface look bad'') subplot 122 bar3(Z) title(''The color is not by height'')

Traté de buscar las propiedades de color en los identificadores devueltos por bar3 (como CData y FaceColor ) pero me perdí con todos los valores y cómo se relacionan con las barras en sí.

En última instancia, me gustaría tener una solución general que para 2 matrices Z y C I pueda crear un diagrama de barras 3D con barras en altura dadas por Z y colores dados por C

¿Como lo puedo hacer?


Esta es una respuesta parcial.

El caso de utilizar la altura de la barra como color está cubierto por la documentación oficial de MATLAB . Básicamente, el código de ejemplo se reduce a:

function q45423394 hB = bar3(peaks(25)); colorbar; for indE = 1:numel(hB) hB(indE).CData = hB(indE).ZData; end

Todo lo que debe hacer después es asegurarse de que el colormap sea ​​el que desea.


Si bien encuentro que la solución de EBH es estéticamente más placentera, aquí hay una solución más simple: la interpolación

z = peaks(5); [x,y]=meshgrid(1:0.1:size(z,1),1:0.1:size(z,2)); zn=interp2(z,x,y,''nearest''); % plot it surf(zn,''edgecolor'',''none'',''facecolor'',''interp'')