【问题标题】:Consulting waterfall chart matlab咨询瀑布图matlab
【发布时间】:2020-03-14 17:29:17
【问题描述】:

我试图在 matlab 中创建“咨询”瀑布图,但我很难创建它。我实际上期望会有一种内置的方式来做到这一点。

鉴于此数据:

x = [5, 2, -5, 8, 2, 12];

total = [1, 0, 0 ,0 ,0, 1];

我想做一个瀑布图。

基本上,向量x 具有图表的值,向量总计指示相应列是否为总计列。

所以第一列是 5 并且是总列。第二列是一个二,它不是(所以它加起来)。第三列是减五,所以它减去,依此类推,直到最后一列再次成为总数。下图的样子。

1)如何得到这个数字?

2) 如何用不同的颜色给增加、减少和总计上色?

3) 如何包含连接线?

【问题讨论】:

  • 您好,请稍作说明。对于total 向量,是否总是只有第一个和最后一个值是总计?当您想要连接线时,您希望这些线实际连接到哪里?

标签: matlab charts


【解决方案1】:

方法一

这是使用 MATLAB 的 bar 函数的一种可能解决方案。

假设:

  • total 列始终是第一列和最后一列。

基本思想是使用 Bar 对象的'Baseline' 属性,它允许特定的柱从特定值开始。例如,bar([1,3,5], 'BaseValue', 2) 生成 3 个从值 2 开始的柱:第一个下降 1 个单位,第二个上升 1 个单位,最后一个上升 3 个单位。

不幸的是,从 R2019b 上的测试来看,Axes 上的所有 Bar 对象都必须共享相同的 BaseValue。因此,对于每个 Bar 对象都有自己的 Baseline 值,它们中的每一个都必须位于单独的 Axes 对象上。我们可以通过将一堆 Axes(每个 Bar 一个)叠加在一起来解决这个问题,使除一个之外的所有 Axes 都是透明的。这样所有条形图都将可见。

无论如何,这里的功能。输入是

  • ax(可选):现有 Axes 对象的句柄。如果您已经绘制了其他内容,或者您​​想手动设置轴的各种属性,则可能需要执行此操作。
  • y:所有增量值的向量。 注意:最终值不是必需的,即要重现问题中的情节,请使用y=[5, 2, -5, 8, 2];

该函数将句柄输出到创建的每个 Bar 对象。您可能希望这进一步更改条形的 EdgeColor。

function h = wfall(ax, y)

if nargin == 1
    y = ax;
    ax = gca;
end
if ~strcmp(ax.NextPlot, 'add')
    fprintf('hold on not set for current axes. Overriding.\n');
    hold(ax, 'on');
end

y = y(:); % column vector
n = length(y);
cumy = cumsum(y);

set(ax, 'XLim', [0, n+1]+0.5, 'YLim', [min(min(cumy), 0), max(max(cumy), 0)]);
% colors:
% decrease - red - code as -1
% total - black - code as 0
% increase - blue - code as 1
set(ax, 'CLim', [-1, 1], 'ColorMap', [1 0 0; 0 0 0; 0 0 1]);

% copy a bunch of axes
for i = 1:n
    ax(i+1) = copyobj(ax(1), ax(1).Parent);
end
% Make all subsequent axes invisible
% Make sure all axes will always be the same size by linking properties
set(ax(2:end), 'Color', 'none', 'XColor', 'none', 'YColor', 'none');
linkprop(ax, {'XLim', 'YLim', 'Position', 'DataAspectRatio'});

% define from/to of each bar (except 1st and last)
from = cumy(1:n-1);
to = cumy(2:n);

% color of each bar (except 1st and last)
c = double(y>0) - double(y<0);
c(1) = [];

% first total bar
h = bar(ax(1), 1, from(1), 'CData', 0, 'BaseValue', 0);
% 2nd to 2nd last bars
for i = 1:n-1
    h(end+1) = bar(ax(i+1), i+1, to(i), 'CData', c(i), 'BaseValue', from(i), 'ShowBaseLine', 'off');
end
% last total bar
h(end+1) = bar(ax(1), n+1, cumy(n), 'CData', 0);

% setting FaceColor flat makes the Bars use the CData property
set(h, 'FaceColor', 'flat') 

如下运行代码,生成如下图。

close all;
ax = gca;
h = wfall(ax, y(1:end-1));


方法二

如果您不想将 Axes 对象堆叠在一起,这是另一种解决方案。 在这种情况下,我们做一个额外的假设:

  • 累积值永远不会是负数(例如,我口袋里的现金)

简单地说,我们绘制的每个条都可以被视为一个彩色条(蓝色/红色),部分被较短的白色条覆盖。

function h = wfall2(ax, y)

if nargin == 1
    y = ax;
    ax = gca;
end
if ~strcmp(ax.NextPlot, 'add')
    fprintf('hold on not set for current axes. Overriding.\n');
    hold(ax, 'on');
end

y = y(:); % column vector
n = length(y);
cumy = cumsum(y);


from = cumy(1:n-1);
to = cumy(2:n);

% color values:
%  1 - blue (increase)
%  0 - white
% -1 - red (decrease)
c = double(y>0) - double(y<0);
c(1) = [];

upper = max(cumy(1:n-1), cumy(2:n));
lower = min(cumy(1:n-1), cumy(2:n));


h(1) = bar(ax, 2:n, upper, 'FaceColor', 'flat', 'CData', c);
h(2) = bar(ax, 2:n, lower, 'FaceColor', 'w');
h(3) = bar(ax, 1, cumy(1), 'FaceColor', 'k');
h(4) = bar(ax, n+1, cumy(n), 'FaceColor', 'k');

set(h, 'EdgeColor', 'none')
set(ax, 'CLim', [-1, 1], 'ColorMap', [1 0 0; 0 0 0; 0 0 1]);

运行函数如下:

close all;
ax = gca;
h = wfall2(ax, y(1:end-1));

结果图: 然而,按照我的个人标准,结果有点难看,因为白条将部分覆盖 x 轴。但是,您可以通过将较低的 YLim 设置为负值来解决此问题,即 set(ax, 'YLim', [-0.5 inf])

【讨论】:

    猜你喜欢
    • 2020-01-14
    • 2012-06-27
    • 2021-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多