我有一个Matlab结构,有几个字段,其中3个在这里很有趣:
elec.label %Nx1 cell-array of strings
elec.chanpos %Nx3 matrix of doubles
elec.elecpos %Nx3 matrix of doubles标签包含通道的唯一名称,而chanpos和elecpos包含坐标,其方式是elec.label(1)具有通道1的名称,elec.chanpos(1,:)和elec.elecpos(1,:)具有通道1的坐标。
我需要的是创建一个类似的结构,它是elec的一个子集,包含标签和两个坐标字段,并且基于我所拥有的标签列表。我所拥有的标签不一定与elec.label数组中使用的大写字母匹配。
我是如何实现这个的:
list46={'fpz';'afz';};%Real list is really long, so I truncated it.
INDX46=[];
for i=1:length(elec.label)
for j=1:length(list46)
if(strcmpi(list46(j),elec.label(i)))
INDX46=[INDX46; i;];
end
end
end
elec46.chanpos=elec.chanpos(INDX46,:);
elec46.elecpos=elec.elecpos(INDX46,:);
elec46.label=elec.label(INDX46,:);我所做的实现,对我来说,感觉就像是在用Matlab编程C。我正在寻找一种更有效的,或至少更多的马塔巴斯克的方式来做到这一点。
发布于 2019-05-28 18:57:25
INDX46=[INDX46; i;];是附加到向量的一种非常慢的方式。相反,请执行INDX46(end+1) = i;。
当以这种首选的方式附加到矩阵时,MATLAB实际上扩展了向量的存储。MATLAB将使底层内存块的大小加倍,以便重复添加将是最优的(O(log )而不是O( n) )。也就是说,大多数循环迭代--数据不需要复制--就可以扩展数组。
相反,第一种追加方法实际上创建了一个新数组,并将旧数组和新值复制到其中。解释器不使用扩展数组的最优O(log )方法。
有关演示上述内容的实验,请参见关于堆栈溢出的问答。
OP中没有任何数据可以很容易地用于测试修改,但在我看来,双循环是比较list46的每个元素和elec.label的每个元素,以便在后者中找到包含前者的一个元素的索引。通过将两个列表按字母顺序排序,可以大大加快这个循环的速度。对于两个排序的列表,一个只需要遍历两个列表一次就可以找到所有的匹配。该算法从O(nm)到O(n+m),两个阵列的长度分别为n和m。
MATLAB有一个函数ismember,它就是这样做的:
INDX46 = ismember(elec.label, list46);发布于 2017-04-19 20:54:53
下面的向量化表单可以替换您的双循环:
INDX46 = sort(cell2mat(cellfun(@(x)find(strcmp(x,elec.label)),list46,'UniformOutput',false)))'(如果INDX46的顺序无关紧要,则可以删除sort函数)。
https://codereview.stackexchange.com/questions/158110
复制相似问题