overwriting certain lines in a matrix with previous lines that satisfy a condition.
1 次查看(过去 30 天)
显示 更早的评论
Hi.
I have a vector which marks rows that needs to be overwritten in a matrix.
The marked rows should be replaced with the previously row that isn't marked.
Line 1 will never be marked so no need to take account for the potential error.
The matrix is big and will always have enough rows that markedrows refers to.
Ex:
Vector: markedrows = [3,6,7,14,15,16,17] (markedrows will always be in ascending order)
So the deal is, according to markedrows, in the matrix:
- The new line 3 should be the same as line 2
- The new line 6 should be the same as line 5
- The new line 7, however, shouldn't be line 6 cause line 6 is marked too, it should instead be line 5.
Following this pattern would make line 14, 15, 16 and 17 all turn into line 13.
I hope this makes sence and that you can help :).
0 个评论
采纳的回答
Guillaume
2014-11-18
Simply do:
for row = markedrows
m(row, :) = m(row-1, :);
end
row 14 is replaced by row 13, row 15 by row 14 which is now equal to row 13, etc.
8 个评论
Guillaume
2014-11-18
编辑:Guillaume
2014-11-18
The syntax I used for the loop doesn't have a backward mode. It just goes through the columns of the vector in the order they're in. Hence, you need to fliplr the original markedrows:
markedrows = [3,6,7,14,15,16,17];
assert(max(markedrows) < size(m, 1)); %make sure you're not marking the last row.
for row = fliplr(markedrows)
m(row, :) = m(row+1, :)
end
更多回答(2 个)
Kelly Kearney
2014-11-18
marked = [3,6,7,14,15,16,17];
good = setdiff(1:20, marked);
prev = arrayfun(@(x) good(find(good < x,1,'last')), marked)
prev =
2 5 5 13 13 13 13
3 个评论
Guillaume
2014-11-18
It uses arrayfun to go through all the elements in marked. For each element in marked, it find the greatest ( last) value that is not ( setdiff) part of marked. That's the index of the row you need to use to replace each row in marked.
Kelly Kearney
2014-11-18
Guillaume's method is more efficient if you just need to replace the rows and be done with it, but if you want a record of which rows were replaced with which, this is an alternative.
And just run
m(marked,:) = m(prev,:);
to do the actual replacement.
Andrew Reibold
2014-11-18
编辑:Andrew Reibold
2014-11-18
This is not the most efficient memory-wise, but it is a working solution and I tried to use basic commands. I just made up a matrix m to demonstrate. See the comment for change that will let you increment the other direction if you want.
m = round(rand(2,20)'*10) %a random matrix of numbers 1-10
markedrows = [3,6,7,14,15,16,17];
new_m = m;
for row = 1:size(m,1)
nrow = row;
while find(markedrows == nrow);
nrow = nrow-1; %make this MINUS a PLUS to swap direction.
new_m(row,:) = m(nrow,:);
end
end
new_m %outputs to command window for comparison
5 个评论
Andrew Reibold
2014-11-18
编辑:Andrew Reibold
2014-11-18
Short answer - Yes, there are better solutions. :D
For now, go check Guillaumes solution again. I actually think his solution is superior in many ways now that I correctly realize what it is doing.
It would be WAY better for large matrices because it only spends time where necessary.
另请参阅
类别
在 Help Center 和 File Exchange 中查找有关 Logical 的更多信息
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!