Optimizing code, removing “for loop”
我正在尝试从Brownlees&Gallo 2006(如果您感兴趣的话)之后的壁虱数据系列中去除异常值。
该代码可以正常工作,但是考虑到我正在处理很长的向量(最大的向量有2000万个观测值,而20h之后未进行计算),我想知道如何加快它的速度。
到目前为止,我所做的是:
我将时间和日期格式更改为数字双精度,我发现它在处理和大量内存方面节省了很多时间。
我为向量分配了内存:
1 2 3 4 5 6 |
这是我想删除的循环。我读到矢量化将大大加快速度,尤其是使用长矢量时。
1 2 3 4 5 6 7 | for i = k+1:n trimmed_mean(i) = trimmean(x(i-k:i-1 & i+1:i+k),10,'round'); %trimmed mean computed on the 'k' closest observations to 'i' (i is excluded) score(i) = x(i) - trimmed_mean(i); sd(i) = std(x(i-k:i-1 & i+1:i+k)); %same as the mean tmp = abs(score(i)) > (alpha .* sd(i) + gamma); out_mat(i) = tmp*1; end |
这是我想做的
1 2 3 4 5 |
但是鉴于我对Matlab完全陌生,所以我不知道如何正确构造相邻观测值的矩阵。我只是认为它的形状应为:
编辑:具体来说,我正在尝试做(但我不能)是:
给定" x"中每个观测值" i"的列向量" x"(n,1),我想将" k"个相邻观测值取到" i"(从ik到i-1以及从i + 1到i + k),并将这些观察结果作为矩阵的行(n,2 * k)。
编辑2:我对代码进行了一些更改,我想我越来越接近解决方案。我发布了另一个特定于我认为现在是问题的问题:
Matlab:使用列向量中的移动间隔填充矩阵行,而无需for循环
我现在想做的是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | [n] = size(price,1); x = price; [j1]=find(x); matrix_left=zeros(n, k,'double'); matrix_right=zeros(n, k,'double'); toc matrix_left(j1(k+1:end),:)=x(j1-k:j1-1); matrix_right(j1(1:end-k),:)=x(j1+1:j1+k); matrix_group=[matrix_left matrix_right]; trimmed_mean=trimmean(matrix_group,10,'round',2); score=bsxfun(@minus,x,trimmed_mean); sd=std(matrix_group,2); temp = abs(score) > (alpha .* sd + gamma); outmat = temp*1; |
我在创建matrix_left和matrix_right时遇到问题。
j1,我用于建立索引的是带有价格观察值索引的列向量。输出很简单
1 | j1=[1:1:n] |
price是大小为(n,1)的double的列向量
对于您的重塑,可以执行以下操作:
1 2 | idxArray = bsxfun(@plus,(k:n)',[-k:-1,1:k]); reshapedArray = x(idxArray); |
感谢乔纳斯(Jonas)向我展示了前进的道路:
1 2 3 4 5 6 7 8 9 10 11 12 13 | idxArray_left=bsxfun(@plus,(k+1:n)',[-k:-1]); %matrix with index of left neighbours observations idxArray_fill_left=bsxfun(@plus,(1:k)',[1:k]); %for observations from 1:k I take the right neighbouring observations, this way when computing mean and standard deviations there will be no problems. matrix_left=[idxArray_fill_left; idxArray_left]; %Just join the two matrices and I have the complete matrix of left neighbours idxArray_right=bsxfun(@plus,(1:n-k)',[1:k]); %same thing as left but opposite. idxArray_fill_right=bsxfun(@plus,(n-k+1:n)',[-k:-1]); matrix_right=[idxArray_right; idxArray_fill_right]; idx_matrix=[matrix_left matrix_right]; %complete index matrix, joining left and right indices neigh_matrix=x(idx_matrix); %exactly as proposed by Jonas, I fill up a matrix of observations from 'x', following idx_matrix indexing trimmed_mean=trimmean(neigh_matrix,10,'round',2); score=bsxfun(@minus,x,trimmed_mean); sd=std(neigh_matrix,2); temp = abs(score) > (alpha .* sd + gamma); outmat = temp*1; |
再次感谢乔纳斯。 你真的让我开心!
也感谢所有看过这个问题并努力帮助您的人!