overwriting certain lines in a matrix with previous lines that satisfy a condition.

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 :).

 採用された回答

Guillaume
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 件のコメント

Søren
Søren 2014 年 11 月 18 日
you are right, thank you.
However, what if I want to turn line 3 into line 4, turn line 6 and 7 into line 8 and turn line 14, 15, 16 and 17 into line 18?
Would it work if I simply turn "markedrows" around and run it through the same way only this time "backwards"? if so, how would you write a code to turn a vector backwards so it could be done on any vector.
Andrew Reibold
Andrew Reibold 2014 年 11 月 18 日
This solution will not work because turning 15 into row 14 is incorrect
Søren
Søren 2014 年 11 月 18 日
I've tried your solution now and it does not work like it should. For example, instead of turning row 15 into row 14 (which now should be 13) it turns row 15 into the old row 14. This goes with all of the rows.
What? The solution does work:
m = repmat((1:17)', 1, 5);
markedrows = [3,6,7,14,15,16,17];
for row = markedrows
m(row, :) = m(row-1, :);
end
m
displays:
m =
1 1 1 1 1
2 2 2 2 2
2 2 2 2 2
4 4 4 4 4
5 5 5 5 5
5 5 5 5 5
5 5 5 5 5
8 8 8 8 8
9 9 9 9 9
10 10 10 10 10
11 11 11 11 11
12 12 12 12 12
13 13 13 13 13
13 13 13 13 13
13 13 13 13 13
13 13 13 13 13
13 13 13 13 13
Guillaume
Guillaume 2014 年 11 月 18 日
And yes, to go the other way, you just reverse the order of markedrows and obviously add one to the row instead of subtracting one.
This time round it's the last row that you need to ensure is not present in markedrow.
Andrew Reibold
Andrew Reibold 2014 年 11 月 18 日
編集済み: Andrew Reibold 2014 年 11 月 18 日
Nevermind. You are genius, my bad. I think we were both forgetting it was pulling a recently updated value rather than the original.
+1 to your answer from me, nice. And so concise.
When you change the sign, do you need to also need to go through the loop backwards to get the same effect?
Guillaume
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
Søren
Søren 2014 年 11 月 18 日
I must have done a typo the first time I ran it then, it works perfectly now.
Thanks alot to both of you, you've been very helpful!

サインインしてコメントする。

その他の回答 (2 件)

Kelly Kearney
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 件のコメント

Søren
Søren 2014 年 11 月 18 日
Sorry, I am not familiar with theese commands. Would you care to explain what is happening in the two lines?
Guillaume
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.
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
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
Andrew Reibold 2014 年 11 月 18 日
If you want to keep the original matrix, assign the data to new_m or something instead of m (so it doesn't edit the original)
Søren
Søren 2014 年 11 月 18 日
I cant get your solution to work on my matrix. I dont have a collunm in my matrix which has the values of the line number so I cant find any rows the way you just did with a [1:20]'.
How would you edit this solution to work on any randomly generated matrix?
Andrew Reibold
Andrew Reibold 2014 年 11 月 18 日
編集済み: Andrew Reibold 2014 年 11 月 18 日
I edited the solution above to fix that, I had made a silly mistake.
Also, I tried to make it compatible with any size 2D matrix, and also made the solution into a new matrix instead of overwriting the original - so that you can compare. Let me know how it goes.
Søren
Søren 2014 年 11 月 18 日
thank you very much!
Last question for you and I'm out. When I first stated that I had a big matrix it might have been abit underestimated, its huge.
While this solution works perferctly, I'm curious if there is a more suitable sulotion for a huge matrix where I dont have to loop though the entire matrix when I've allready found out which lines needs to be altered?
Andrew Reibold
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.

サインインしてコメントする。

カテゴリ

ヘルプ センター および File ExchangeLoops and Conditional Statements についてさらに検索

質問済み:

2014 年 11 月 18 日

コメント済み:

2014 年 11 月 18 日

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by