【问题标题】:Vertically offset stem plot垂直偏移的茎图
【发布时间】:2025-11-27 16:35:01
【问题描述】:

我如何垂直偏移stem 图,以便茎从 y == 0.5 而不是从 x 轴发出?

我知道我可以更改 x-tick-marks,但最好只更改情节。

stem(X+0.5) 不起作用,因为它只会使茎变长。

我也有正面和负面的数据。而且我在同一轴上还有其他图,我不想偏移。


根据 Luis Mendo 在下面的回答,我为此编写了一个函数(但是请参阅 my answer below,因为 MATLAB 实际上对此有一个内置属性):

function stem_offset(x_data, y_data, offset, offset_mode, varargin)
%STEM_OFFSET stem plot in which the stems begin at a position vertically
%offset from the x-axis.
%
%   STEM_OFFSET(Y, offset) is the same as stem(Y) but offsets all the lines
%   by the amount in offset
%
%   STEM_OFFSET(X, Y, offset) is the same as stem(X,Y) but offsets all the
%   lines by the amount in offset
%
%   STEM_OFFSET(X, Y, offset, offset_mode) offset_mode is a string
%   specifying if the offset should effect only the base of the stems or
%   also the ends. 'base' for just the base, 'all' for the baseand the
%   ends. 'all' is set by default
%
%   STEM_OFFSET(X, Y, offset, offset_mode, ...) lets call all the stem()
%   options like colour and linewidth etc as you normally would with
%   stem().

    if nargin < 3
        offset = 1:length(y_data);
        y_data = x_data;
    end
    if nargin < 4
        offset_mode = 'all';
    end

    h = stem(x_data, y_data, varargin{:});
    ch = get(h,'Children');

    %Offset the lines
    y_lines = get(ch(1),'YData'); %// this contains y values of the lines

    %Offset the ends
    if strcmp(offset_mode, 'all')
        set(ch(1),'YData',y_lines+offset)
        y_ends = get(ch(2),'YData'); %// this contains y values of the ends
        set(ch(2),'YData',y_ends+offset) 
    else
        set(ch(1),'YData',y_lines+offset*(y_lines==0)) %// replace 0 (i.e. only the start of the lines) by offset
    end

end

我现在已经上传到文件交换 (http://www.mathworks.com/matlabcentral/fileexchange/45643-stem-plot-with-offset)

【问题讨论】:

    标签: matlab plot


    【解决方案1】:

    以下似乎有效。显然,stem 对象的第一个子对象包含垂直线,因此您只需将其 YData 属性中的所有 0 值更改为所需的偏移量:

    delta = .5; %// desired offset
    h = stem(1:10); %// plot to be offset. Get a handle
    
    ch = get(h,'Children');
    yy = get(ch(1),'YData'); %// this contains y values of the lines
    set(ch(1),'YData',yy+delta*(yy==0)) %// replace 0 by delta
    

    一个包含正数据和负数据的示例,以及同一轴上的其他图:

    stem(.5:4.5,ones(1,5),'g') %// not to be offset
    hold on
    h = stem(1:5,[-2 3 -4 1 -1]); %// to be offset
    axis([0 5.5 -5 4])
    
    ch = get(h,'Children');
    yy = get(ch(1),'YData'); %// this contains y values of the lines
    set(ch(1),'YData',yy+delta*(yy==0)) %// replace 0 by delta
    

    【讨论】:

    • 谢谢 Luis,这太完美了。奇怪的是,ch 在调试时看起来只是一个 2×1 双向量。我已经把它包装成一个函数,我会把它添加到我的问题中,看看。
    • @Dan 我做了一个小的更正(右括号)。是的,我认为将其提交给 File Exchange 会很好,因为其他人可能会觉得它有用
    • 再次感谢。我已经提交了(mathworks.com/matlabcentral/fileexchange/…
    【解决方案2】:

    您可以在调用stem 后立即在茎上绘制一个白色矩形。

    x = 1:10
    
    stem(x)
    
    fudge=0.05
    rectangle('Position', [min(x) * range(x)*fudge, 0.5*fudge, range(x)*(1+2*fudge), 0.5-fudge], 'FaceColor', 'w', 'EdgeColor', 'w')
    

    fudge 用于避免在轴上绘画,并确保覆盖最左侧和最右侧的茎。

    【讨论】:

    • +1 但这不会覆盖以前的情节吗?该问题指定该图可能包含其他图
    • @LuisMendo 是的,它会覆盖其他地块。您可以通过先绘制茎,重新绘制,然后再绘制其他图来解决此问题。您还可以修改此方法以在各个茎上绘制一系列细小的矩形;那么茎之间的区域不会受到影响 - 但实际上我的答案是一个简单、快速和肮脏的解决方案。
    • 谢谢,这是一个好主意,但它不会帮助茎朝另一个方向发展。无论如何 +1,但我肯定会坚持 Luis 的方法
    【解决方案3】:

    看来stem 中实际上有一个属性,我不知何故错过了!

    http://www.mathworks.com/help/matlab/ref/stem.html#btrw_xi-87

    例如来自文档:

    figure
    X = linspace(0,2*pi,50)';
    Y = (exp(0.3*X).*sin(3*X));
    h = stem(X,Y);
    set(h,'BaseValue',2);
    

    【讨论】:

      最近更新 更多