加速代码以比较结构中的字段

时间:2016-05-05 08:26:31

标签: performance matlab struct

我有结构Trajectories,字段uniqueDate,dateAll,label:我想比较字段uniqueDate和dateAll,如果有对应关系,我会在标签中保存其他结构的值。

我写了这段代码:

for k=1:nCols
    for j=1:size(Trajectories(1,k).dateAll,1)
        for i=1:size(Trajectories(1,k).uniqueDate,1)
            if (~isempty(s(1,k).places))&&(Trajectories(1,k).dateAll(j,1)==Trajectories(1,k).uniqueDate(i,1))&&(Trajectories(1,k).dateAll(j,2)==Trajectories(1,k).uniqueDate(i,2))&&(Trajectories(1,k).dateAll(j,3)==Trajectories(1,k).uniqueDate(i,3))
                for z=1:24
                    if(Trajectories(1,k).dateAll(j,4)==z)&&(size(s(1,k).places.all,2)>=size(Trajectories(1,k).uniqueDate,1))
                        Trajectories(1,k).label(j)=s(1,k).places.all(z,i);
                    else if(Trajectories(1,k).dateAll(j,4)==z)&&(size(s(1,k).places.all,2)<size(Trajectories(1,k).uniqueDate,1))
                            for l=1:size(s(1,k).places.all,2)
                                Trajectories(1,k).label(l)=s(1,k).places.all(z,l);
                            end
                        end
                    end
                end
            end
        end
    end
end

E.g

Trajectories(1,4).dateAll=[1 2004 8 1 14 1 15 0 0 0 1 42 13 2;596 2004 8 1 16 20 14 0 0 0 1 29 12 NaN;674 2004 8 1 18 26 11 0 0 0 1 20 38 1;674 2004 8 2 10 7 40 0 0 0 14 26 5 3;674 2004 8 2 11 3 29 0 0 0 1 54 3 3;631 2004 8 2 11 57 56 0 0 0 0 30 8 2;1 2004 8 2 12 4 35 0 0 0 1 53 21 2;631 2004 8 2 12 52 58 0 0 0 0 20 36 2;631 2004 8 2 13 5 3 0 0 0 1 49 40 2;631 2004 8 2 14 0 20 0 0 0 1 56 12 2;631 2004 8 2 15 2 0 0 0 0 1 57 39 2;631 2004 8 2 16 1 4 0 0 0 1 55 53 2;1 2004 8 2 17 9 15 0 0 0 1 48 41 2];

Trajectories(1,4).uniqueDate= [2004 8 1;2004 8 2;2004 8 3;2004 8 4];

它运行但它非常慢。如何修改它以加快速度?

1 个答案:

答案 0 :(得分:1)

让我们从内到外工作,看看它在哪里。

第1步:简化比较条件:

if (~isempty(s(1,k).places))&&(Trajectories(1,k).dateAll(j,1)==Trajectories(1,k).uniqueDate(i,1))&&(Trajectories(1,k).dateAll(j,2)==Trajectories(1,k).uniqueDate(i,2))&&(Trajectories(1,k).dateAll(j,3)==Trajectories(1,k).uniqueDate(i,3))

变为

if (~isempty(s(1,k).places)) && all( Trajectories(1,k).dateAll(j,1:3)==Trajectories(1,k).uniqueDate(i,1:3) )

然后我们想从for循环中删除它。 “交叉”功能在这里很有用:

[ia i1 i2]=intersect(Trajectories(1,k).dateAll(:,1:3),Trajectories(1,k).uniqueDate(:,1:3),'rows');

我们现在有i1中与dateAll相交的所有行的向量uniqueDate

现在我们可以使用类似的方法删除比较z的循环:

[iz iz1 iz2] = intersect(Trajectories(1,k).dateAll(i1,4),1:24);

我们必须使用子集的子集来注意我们的索引。

这将代码简化为:

for k=1:nCols
    if isempty(s(1,k).places)
        continue; % skip to the next value of k, no need to do the rest of the comparison
    end
    [ia i1 i2]=intersect(Trajectories(1,k).dateAll(:,1:3),Trajectories(1,k).uniqueDate(:,1:3),'rows');
    [iz iz1 iz2] = intersect(Trajectories(1,k).dateAll(i1,4),1:24);

    usescalarlabel = (size(s(1,k).places.all,2)>=size(Trajectories(1,k).uniqueDate,1);
    if (usescalarlabel)
        Trajectories(1,k).label(i1(iz1)) = s(1,k).places.all(iz,i2(iz1));
    else
        % you will need to check this: I think here you were needlessly repeating this step for every match
        Trajectories(1,k).label(i1(iz1)) = s(1,k).places.all(iz,:); 
    end
end

但是等等!该z循环与使用索引完全相同。所以我们毕竟不需要第二次交叉:

for k=1:nCols
    if isempty(s(1,k).places)
        continue; % skip to the next value of k, no need to do the rest of the comparison
    end
    [ia i1 i2]=intersect(Trajectories(1,k).dateAll(:,1:3),Trajectories(1,k).uniqueDate(:,1:3),'rows');

    usescalarlabel = (size(s(1,k).places.all,2)>=size(Trajectories(1,k).uniqueDate,1);
    label_indices = Trajectories(1,k).dateAll(i1,4);
    if (usescalarlabel)
        Trajectories(1,k).label(label_indices) = s(1,k).places.all(label_indices,i2);
    else
        % you will need to check this: I think here you were needlessly repeating this step for every match
        Trajectories(1,k).label(label_indices) = s(1,k).places.all(label_indices,:);
    end
end

你需要检查索引 - 我确定我在某个地方犯了一个错误而没有数据进行测试,但这应该会让你知道如何继续删除循环并使用向量表达式代替。没有看到我可以优化的数据。如果您可以将数据重新格式化为一组3d矩阵/单元格而不是使用结构,则可以更进一步。

我怀疑你的情况我称之为“usescalarlabel” - 看起来你混合了两种数据类型。此外,我强烈建议将dateAll矩阵分成单独的“日期”和“数据”矩阵,因为行索引4以后似乎不是日期。您复制/粘贴的示例似乎在行索引1处有一个额外的值?在这种情况下,您需要比较Trajectories(1,k).dateAll(:,2:4)而不是Trajectories(1,k).dateAll(:,1:3)

祝你好运。