Reputation: 909
Note that I'm using Matlab R2013b. So, I have a toy input matrix of 10x2 size:
inputM = [NaN 4 7 NaN 9 NaN NaN NaN NaN NaN; NaN NaN 8 10 2 NaN 3 NaN NaN NaN]
I have the lowest and highest positions where the non-NaN values are located in each column:
lowest_idx = [2 3]
highest_idx = [5 7]
I want to shift the bulk rows, between the lowest and highest positions, downward according to a shifting index shift_idx = [3 2]
. The output matrix I need to obtain looks like
outputM = [NaN NaN NaN NaN 4 7 NaN 9 NaN NaN; NaN NaN NaN NaN 8 10 2 NaN 3 NaN]
I can do this using a for loop
like this:
for i = 1:length(shift_idx)
inputM(lowest_idx(i)+shift_idx(i):highest_idx(i)+shift_idx)(i),i) = inputM(lowest_idx(i):highest_idx(i),i);
inputM(1:lowest_idx(i)+1,i) = nan;
end
However, my real matrix has over 1 million columns, so I'd like a more efficient solution. Anyone has an idea of how to do this without a for loop
?
Upvotes: 0
Views: 76
Reputation: 9875
If you can access Matlab R2016a, use circshift. For example,
outputM = circshift(inputM, shift_idx);
If you don't have modern version of circshift
, you will need to use the old version twice. Once along each dimension. For example,
for i = 1:numel(size(shift_idx))
outputM = circshift(inputM, shift_idx(i),i);
end
WARNING: the above is not intended to accomplish exactly what you asked. But give it a try. You will see what it does.
In your particular problem, since you are treating each row differently, the shift is going to be more computationally demanding. You can nevertheless use circshift
. For example,
outputM = [circshift(inputM(:,1), shift_idx(1),2); circshift(inputM(:,1), shift_idx(2),2)];
Make sure you read the documentation and do testing on simple examples first though. You also need to know the behaviors of how the unfilled elements are moved.
Upvotes: 0
Reputation: 19689
circshift
does exactly this.
outputM = circshift(inputM.', shift_idx).';
Upvotes: 0