在Matlab中,我有两个包含坐标的大矩阵(A和B)。两条线代表x和y,每列代表一个笛卡尔坐标(x; y)。
现在我想将矩阵B中距离小于1(米)的所有点存储到矩阵A中任意点的新矩阵中。
我可以遍历所有数据,但这非常耗时(矩阵是2x800000)。
有没有办法提升表现?
这是我当前代码的结构:
new_vec = [0;0];
for i=1:length(A)
cur_x = A(1, i);
cur_y = A(2, i);
for j=1:length(B)
if B(2, j) <= cur_y + 1 && B(2, j) >= cur_y - 1 && ...
B(1, j) <= cur_x + 1 && B(1, j) >= cur_x - 1
new_vec = [new_vec, [B(1, j); B(2, j)]];
end
end
end
答案 0 :(得分:3)
另一种选择是使用pdist2
,如下所示:
new_vec = B(:, any(pdist2(A', B', 'Chebychev') < 1, 1));
请注意,pdist2
总是比您的方法更快,但可能比Wolfie的建议慢,因为pdist2
始终计算A
的所有点之间的所有距离B
。
<强>比较强>
我会比较:
pdist2
使用以下示例数据
A = rand(2, N)*N*relativeAmplitude;
B = rand(2, N)*N*relativeAmplitude;
relativeAmplitude
和N=10000
的执行时间:
<强>结论强>
所有解决方案(Wolfie&#39; s,rahnema1&mine和我的)都比原始算法快。
优化(Wolfie)vs pdist2
(我的):如果B
中可能找到A
的索引,那么Wolfie&# 39;答案可能快50倍,但如果不太可能,pdist
可能会快50%。请注意,我的解决方案的执行时间与relativeAmplitude
无关,而沃尔夫不是,但在某些情况下,沃尔夫的回答可能会快得多。
bsxfun
(rahnema1)vs pdist2
(我的):如果没有新的R2016b功能,bsxfun
总是比{{1}慢约50% ,否则两种方法总是(几乎)同样快。
答案 1 :(得分:2)
基于当前实施的性能改进:
% Appending is bad practise for memory management, you should initialise the
% entire output array at first.
new_vec = NaN(size(B));
% You should not use i as a loop variable, since you are overwriting the default i=sqrt(-1)
% Also length(A)=max(size(A)), clearer to use size(A,2)
% Loops have been swapped as we want to exit the *A* looping when satisfied
for jj=1:size(B,2)
% No need to re-assign current variables each loop, waste of time/memory
% Same as before, j also is sqrt(-1) by default!
% We could remove this loop entirely using vectorization, but it's likely quicker to
% loop *until the condition is satisfied* then exit the loop early, avoiding many ops.
for ii=1:size(A,2)
% We can *half* the number of logical operations by using the abs distance!
if abs(B(2,jj)-A(2,ii)) <= 1 && abs(B(1,jj) - A(1,ii)) <= 1
% We pre-allocated, so no need to append - use direct indexing
new_vec(:,jj) = B(:,jj);
% Now the condition is satisfied for B(:,jj), exit the jj loop!
break;
end
end
end
% We initialised an array of NaNs, remove the columns which are still NaN
new_vec(:, isnan(new_vec(1,:))) = [];
亮点:
i
或j
作为循环变量,它们的默认值为sqrt(-1)
abs
进行绝对距离检查,减少逻辑检查次数。B
坐标位于任何 A
坐标的距离内时,您很高兴,提前退出循环以避免更进一步检查。 初始化NaN
的2D数组的一种(可能更加内存友好的)替代方法是初始化布尔false
数组,然后在每个满意的jj
索引处使其成立。最后,我们会new_vec = B(:,booleanVector);
答案 2 :(得分:1)
这是一个矢量化解决方案:
export class MyHeaderComponent {
construct(){ }
private arr:string[]=['az'];
calendarOptions = {
events :[],
//click on day make event
dayClick(date, jsEvent, view) {} ,
renderEvents(event, element, view ){}
}
ngOnInit() {
let newEvents = [
{
title: 'name b',
start: '2017-09-20'
},
{
title: 'name c',
start: '2017-09-20'
},
{
title: 'name d',
start: '2017-09-20'
}
];
this.calendarOptions.events = newEvents;
//callback function
this.calendarOptions.dayClick = (date,jsEv,vie) => {
let abc:string ='a';
//abc = prompt('Enter Title');
let dat = date.format()
let hamz ={
title:abc,
start:dat
};
console.log(hamz);
newEvents.push(hamz);
this.calendarOptions.events = newEvents;
console.log(this.calendarOptions.events);
this.calendarOptions.events = newEvents;
$("#myCalendar").fullCalendar('renderEvents',
newEvents,
true //we want to stick it
);
alert('ok')
}
}
}
从MATLAB r2016b开始,您可以将cur_x = A(1,:);
cur_y = A(2,:);
B1= reshape(B(1,:),[],1);
B2= reshape(B(2,:),[],1);
condition = abs(bsxfun(@minus,B2,cur_y))<=1 & ...
abs(bsxfun(@minus,B1,cur_x))<=1;
[x ,~]=find(condition);
new_vec = [[0;0] B(:,x)];
写为:
condition
或
condition = abs(B2-cur_y)<=1 & ...
abs(B1-cur_x)<=1;
从@Wolfie回答condition = B2 <= cur_y + 1 & B2 >= cur_y - 1 & ...
B1 <= cur_x + 1 & B1 >= cur_x - 1;
被盗的想法。