用 disconnected/discrete 行创建图

Creating plots with disconnected/discrete lines

这是我的代码:

for p = 1:length(id_unique)
    h=figure;
    hold on
    j = 1;
    for i = 1:1:length(id)
        if id_unique(p)==id(i)
            h=plot([startdate(i),enddate(i)],[j,j],'ok-');
            hold on
            j = j + 1;        
        end
    end
    grid on
    hold off
    savefig([plotname,'.fig'])
    print(plotname,'-djpeg','-r300')
    close
end

% id:           integer vector containing 50000 values
% id_unique:    sorted unique values from vector 'id'
% startdate:    datetime vector containing 50000 dates
% enddate:      datetime vector containing 50000 dates

'id'向量中的每个elements/values表示一个事件,其中事件的开始日期和结束日期在'[=29=中的相应位置可用]startdate' 和 'enddate' 向量。 因此,事件 id(1) 的开始日期为 startdate(i),结束日期为 enddate(i).

程序从“id_unique”向量中获取一个值,并针对在“id”中找到的每个匹配值, 它在图中画一条线,表示事件的开始和结束时间。

例如,假设 55 是来自向量 'id_unique' 的一个 id 值,并且我们在 id[= 中有这个值 1000 次41=]。因此,对于 55,创建了一个图,描绘了 1000 条单独的线,在事件开始时有一个标记 'o',在事件结束时有一个标记 'o',并且有一条线连接两个标记。

请查看从该代码块生成的附件图。如果 id_unique 有 70 个值,则将从该代码创建 70 个这样的图。图像中,由于开始日期和结束日期之间的差异很小,因此许多线太小,因此标记相互重叠,看起来像一个点。

现在问题来了,对于“id_unique”中的一个 id-value,我们在“”中有很多它的实例id' 向量。当程序将单条线绘制到 100 条时,它运行得非常快,但在同一图中绘制 300 条线后,程序变慢了。当程序在同一张图中绘制 1000 条线时,每条线大约需要 5-7 秒。所以生成一个多行的图需要很多小时。

有没有办法改进我的代码,使这些绘图生成更快。

考虑更多之后,我现在建议执行以下操作 - 与其在绘图中创建多条线,这会在背景中生成大量对象,不如生成 一个 每个图的行,被分成多个部分。如果 startdate 和 enddate 是 1xlength(id) 的向量,那么下面的代码将更快,因为它将所有行连接在一起,中间有 NaN 值。这使得情节在那一点上断线。一切都非常快,不需要像我之前建议的那样乱用 xlim 和 ylim...

这是我的代码:

for p = 1:length(id_unique)
    h=figure;
    block=[startdate(id==id_unique(p));enddate(id==id_unique(p))];
    x_vals=reshape([block;nan(1,size(block,2))],1,[]);
    y_vals=reshape([(1:size(block,2));(1:size(block,2));nan(1,size(block,2))],1,[]);
    plot(x_vals,y_vals,'ok-');
    grid on
    savefig([plotname,'.fig'])
    print(plotname,'-djpeg','-r300')
    close
end

我希望这对你更好。 (当然,如果您的开始日期和结束日期向量的长度(id)乘以 1,那么您应该在上面的第 3 行中使用 .' 转置它们)。

我不确定单独绘图的目的是什么,但如果有用的话,可以将它们全部绘制在同一个图表上。代码将是:

h=figure;
hold on;
for p = 1:length(id_unique)
    block=[startdate(id==id_unique(p));enddate(id==id_unique(p))];
    x_vals=reshape([block;nan(1,size(block,2))],1,[]);
    y_vals=reshape([(1:size(block,2));(1:size(block,2));nan(1,size(block,2))],1,[]);
    plot(x_vals,y_vals,'Marker','o');
    grid on
end
savefig([plotname,'.fig'])
print(plotname,'-djpeg','-r300')
close

这让 Matlab 使用其标准系列设置线型和颜色。它还允许您使用 legend 函数添加标签。当然,如果 id 中的位置很重要,而不是使用 y_vals 的序列,您可以使用从 find 获得的位置信息,将第 4 行和第 6 行更改为:

[~,index]=find(id==id_unique(p));
block=[startdate(index);enddate(index)];

y_vals=reshape(index;index;nan(1,size(block,2))],1,[]);

然后您会在一张图上看到所有 id,id 的不同值通过颜色和线型区分。然后就可以使用legend函数生成图例了:

legend(num2str(id_unique.'));

(假设id_unique是行向量,如果是列向量,去掉.')。

你不需要循环:

你可以使用类似的东西:

a = 1:0.1:4*pi;
b = sin(a); %vector that represent the start of each line
c = sin(a)+1; %vector that represent the end of each line
plot([b;c],[a;a],'-ko','markersize',2)

结果:

函数plot需要2个参数:x和y,但是,这就是世界美丽的原因,函数plot可以管理多行。如果 x 和 y 是矩阵,matlab 将每列解释为一个新行。

这里是绘制 2 个不同标记的方法:

% some random data:
N = 50;
id = randi(5,N,1);
startdate = sort(randi(100,N,1));
enddate = startdate+randi(10,N,1);

% plotting:
ax = plot([startdate(:).'; enddate(:).'],[1:N; 1:N],'-k',...
    startdate,1:N,'k<',enddate,1:N,'k>')

向量后面的 (:).' 并不是真正需要的,只是为了确保它们会以正确的方向给出 plot - 2 行,startdate 以上 enddate.

(随机):


如果你想按id对数据进行分组,并这样给它们上色,你可以这样做:

N = 30;
id = randi(5,N,1);
startdate = datetime(sort(736000+randi(100,N,1)),'ConvertFrom','datenum');
enddate = startdate+randi(20,N,1);

% plotting:
ax = plot([startdate(:).'; enddate(:).'],[1:N; 1:N],'-',...
    startdate,1:N,'k<',enddate,1:N,'k>');

% coloring:
cmap = colormap('jet');
col = cmap(floor(linspace(1,64,numel(unique(id)))),:);
for k = 1:N
    ax(k).Color = col(id(k),:);
    ax(k).LineWidth = 2;
end

% set the legend:
c = 1;
leg_ent = zeros(numel(unique(id)),1);
for k = unique(id).'
    leg_ent(c) = find(id==k,1,'first');
    c = c+1;
end
legend(ax(leg_ent),num2str(unique(id)),'Location','SouthEast')

你将得到: