使用断开/离散线创建绘图

时间:2016-09-28 12:18:05

标签: matlab plot matlab-figure

这是我的代码:

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 ”向量中的每个元素/值都意味着一个事件,其中事件的startdate和enddate在“ startdate ”中的相应位置可用 enddate '向量。 因此,事件 id(1)的开始日期为 startdate(i),结束日期为enddate(i)。

程序从“ id_unique ”向量中获取值,对于在“ id ”中找到的每个匹配值,它会在图中绘制一条线,表示开头和结束时间。

例如,假设55是来自矢量' id_unique '的id值,我们在 id 中有1000次这个值。因此,对于55,创建的图表描绘了1000个单独的行,在事件开始时标记为“o”,在事件结束时标记为“o”,并且连接两个标记的行。

enter image description here

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

现在问题出现在' id_unique '中的id值时,我们在' id '向量中有很多实例。当程序将各行绘制到100时,它的工作速度非常快,但在同一图中绘制300行后,程序变慢。当程序在同一图中绘制1000行时,每行大约需要5-7秒。因此,需要花费数小时才能生成包含多行的绘图。

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

3 个答案:

答案 0 :(得分:4)

您不需要循环:

你可以使用类似的东西:

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)

<强>结果:

enter image description here

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

答案 1 :(得分:1)

考虑到这一点后,我现在建议执行以下操作 - 而不是在绘图中创建多行,在后台生成大量对象,最好生成一个行每个情节,分为多个部分。如果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

我希望这对你有用。 (当然,如果你的startdate和enddate向量的长度(id)是1,那么你应该使用。&#39;在上面的第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(num2str(id_unique.'));

(这假设id_unique是行向量。如果是列向量,则删除.')。

答案 2 :(得分:1)

以下是绘制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 }。

给出(随机):

2_mark

如果要按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')

你会得到:

2mark_by_id