0
votes

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?

2

2 Answers

0
votes

circshift does exactly this.

outputM  = circshift(inputM.', shift_idx).';
0
votes

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.