How to handle large matrices
3 views (last 30 days)
Show older comments
I have a general problem, when I want to work with large matrices. The calculation time of my script is around 2 weeks - far too much. I am sure, that the solution is quite simple for someone, who is more experienced with Matlab programming.
Problem with 2 matrices:
pc_raw = 23617489x12 double
fw_raw = 35631184x5 double
Now I want to find for each value in pc_raw(:,1) the corresponding value in fw_raw(:,1) and copy fw_raw(corr_value, 1:5) to pc_raw(corr_value, 8:12).
Example:
pc_raw = 1 1 3 3 4 5 6 7 8 9 10
fw_raw = 1 1 1 2 2 3 3 4 4 5 6 7 8 8 9 10
My script so far:
for k=1:len_pc_raw
pc_timestep = pc_raw(k,1);
NaN_test = isnan(pc_raw(k,8));
if NaN_test == 1
pc_temp = find(pc_raw(:,1)==pc_timestep);
fw_temp = find(fw_raw(:,1)==pc_timestep);
empty_test = isempty(fw_temp);
if empty_test == 0
len_pc_temp = length(pc_temp);
len_fw_temp = length(fw_temp);
if len_pc_temp <= len_fw_temp
for j=1:len_pc_temp
pc_echo = pc_temp(j); fw_echo = fw_temp(j);
pc_raw(pc_echo,8:12) = fw_raw(fw_echo,1:5);
end
else
for j=1:len_fw_temp
pc_echo = pc_temp(j); fw_echo = fw_temp(j);
pc_raw(pc_echo,8:12) = fw_raw(fw_echo,1:5);
end
end
end
end
end
Any idea how to speed up the calculation time? I would be very grateful for any comments!
7 Comments
James Tursa
on 16 Feb 2012
What do you want to have happen in the following cases:
1) Value in pc_raw(:,1) is not found in fw_raw(1,:)
2) Value in pc_raw(:,1) has multiple matches in fw_raw(1,:)
3) Multiple same values in pc_raw(:,1)
Once I know these answers I can post m-code and/or a mex routine that should work pretty fast.
Accepted Answer
the cyclist
on 16 Feb 2012
This should work, if you are guaranteed that every value of pc_raw(:,1) is in fact in fw_raw(:,1), and is unique. If not, you will need to do some more work.
[tf,loc] = ismember(pc_raw(:,1),fw_raw(:,1));
pc_raw(:,8:12) = fw_raw(loc,:);
EDIT IN RESPONSE TO COMMENTS:
Here is a fuller piece of code in which I have tried to be very explicit about what I am doing. I hope this helps.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% This part of the code creates two sample input arrays
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
rng(2)
N = 3;
M = 7;
pc_raw = rand(N,12);
fw_raw = rand(M,5);
fw_raw(M+1,:) = fw_raw(M,:);
fw_raw(M+1,2) = fw_raw(M+1,2) + 0.1
index = randperm(M);
pc_raw(:,1) = fw_raw(index(1:N),1)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% This part of the code implements the algorithm
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% First step:
% For each row of pc_raw, find the corresponding row of fw_raw
% that has the same first element
[tf,loc] = ismember(pc_raw(:,1),fw_raw(:,1))
% Second step:
% For every row of pc_raw, insert the all columns of
% fw_raw (for the correct row!) into columns 8:12 of pc_raw
pc_raw(:,8:12) = fw_raw(loc,:)
8 Comments
the cyclist
on 16 Feb 2012
I don't fully understand what you want to happen for (1) repeated values in the first column of pc_raw, (2) repeated values in the first column of fw_raw, or (3) the same repeated value in both.
You might get some value out of first applying the unique() function to your first columns, which will identify the locations of the repeats.
More Answers (1)
James Tursa
on 17 Feb 2012
Here is some m-code for what I think you want:
m1 = size(pc_raw,1);
m2 = size(fw_raw,1);
k2 = 1;
for k1=1:m1
if( isnan(pc_raw(k1,8)) )
while( pc_raw(k1,1) > fw_raw(k2,1) )
k2 = k2 + 1;
if( k2 > m2 )
break;
end
end
if( k2 > m2 )
break;
end
if( pc_raw(k1,1) == fw_raw(k2,1) )
pc_raw(k1,8:12) = fw_raw(k2,1:5);
k2 = k2 + 1;
if( k2 > m2 )
break;
end
end
end
end
It relies heavily on the fact that the first column of each array is pre-sorted in ascending order as you stated.
And here is a mex implementation (CAUTION: No argument checking)
EDIT: 17-Feb-2012 changed location of mxUnshareArray
/* findrep(pc_raw,fw_raw); */
#include "mex.h"
#ifndef MWSIZE_MAX
#define mwSize int
#endif
void mxUnshareArray(mxArray *);
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
mwSize m1, m2, k1, k2;
double *Apr1, *Apr8, *Apr9, *Apr10, *Apr11, *Apr12;
double *Bpr1, *Bpr2, *Bpr3, *Bpr4, *Bpr5;
mxUnshareArray(prhs[0]);
m1 = mxGetM(prhs[0]);
m2 = mxGetM(prhs[1]);
Apr1 = mxGetPr(prhs[0]);
Bpr1 = mxGetPr(prhs[1]);
Apr8 = Apr1 + m1*7;
Apr9 = Apr8 + m1;
Apr10 = Apr9 + m1;
Apr11 = Apr10 + m1;
Apr12 = Apr11 + m1;
Bpr2 = Bpr1 + m2;
Bpr3 = Bpr2 + m2;
Bpr4 = Bpr3 + m2;
Bpr5 = Bpr4 + m2;
k2 = 0;
for( k1=0; k1<m1; k1++ ) {
if( mxIsNaN(Apr8[k1]) ) {
while( Apr1[k1] > Bpr1[k2] ) {
if( ++k2 == m2 ) {
return;
}
}
if( Apr1[k1] == Bpr1[k2] ) {
Apr8[k1] = Bpr1[k2];
Apr9[k1] = Bpr2[k2];
Apr10[k1] = Bpr3[k2];
Apr11[k1] = Bpr4[k2];
Apr12[k1] = Bpr5[k2];
if( ++k2 == m2 ) {
return;
}
}
}
}
}
To use the mex code, put it in a file on the MATLAB path, e.g. findrep.c, and then do this:
mex findrep.c
Call it without any output arguments, e.g.,
findrep(pc_raw,fw_raw);
See Also
Categories
Find more on Performance and Memory in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!