3

There are two matrices; the first one is my input matrix

enter image description here

and the second one ("renaming matrix") is used to replace the values of the first one

enter image description here

That is, looking at the renaming matrix; 701 must be replaced by 1,...,717 must be replaced by 10,etc.. such that the input matrix becomes as such

enter image description here

The ? values are defined but i didn't put them. The second column of the input matrix is already sorted(ascending order from top down) but the values are not consecutive(no "710": see first pic).

The question is how to get the output matrix(last pic) from the first two.

Phonon
  • 12,549
  • 13
  • 64
  • 114
K. Rmth
  • 217
  • 4
  • 12
  • maybe you can use this : [containers.Map][1] [1]: http://stackoverflow.com/a/3592050/2070074 – DavidK Feb 13 '13 at 22:27

3 Answers3

2

Looks to me like it's screaming for a sparse matrix solution. In matlab you can create a sparse matrix with the following command:

SM = sparse( ri, ci, val );

where ri is the row index of the non-zero elements, ci is the corresponding column index, and val is the values.

Let's call your input matrix IM and your lookup matrix LUM, then we construct the sparse matrix:

nr = size(LUM, 1);
SM = sparse( ones(nr, 1), LUM(:, 1), LUM(:, 2) );

Now we can get your result in a single line:

newMatrix = reshape(SM(1, IM), size(IM));

almost magic.

I didn't have a chance to check this tonight - but if it doesn't work exactly as described, it should be really really close...

Floris
  • 45,857
  • 6
  • 70
  • 122
  • It isn't working, IM is <36x2> and LUM is <37X2> giving me an "Index exceeds matrix dimensions." error. – K. Rmth Feb 14 '13 at 10:49
  • The error suggests there is a value in IM that doesn't occur in the first col of LUM. Can you print `max(IM(:))` and `max(LUM(1.:))`? They ought to be the same? – Floris Feb 14 '13 at 11:42
  • max(IM(:)) and max(LUM(1,:)) are the same and are equal to 799. I inadvertently swapped the columns of LUM in the pic above but your method works like a charm although "newMatrix" needs reshaping; as you said almost magic!! – K. Rmth Feb 14 '13 at 12:24
  • Super. I added the reshape statement - please confirm this now matches the question as asked... – Floris Feb 14 '13 at 13:40
  • 1
    This is a very elegant solution, however there's one potential flaw, which depends on how the problem is precisely stated. The flaw is that if a value is not replaced, then it's going to get set to 0 in your solution. For example, if we want to change 701 to 1, but we want to leave 799 alone, `{701 799}` will be replaced by `{1 0}`, not `{1 799}`. – Phonon Feb 14 '13 at 19:36
  • 1
    @Phonon - thanks for pointing that out. You are right: I am making the implicit assumption that all values in the input matrix have a corresponding value in the lookup matrix. This could be addressed. For example, if there are no elements in the lookup matrix that point to zero, then you could test for zero after replacing, and putting things back how they were... But I don't think that was what the OP was asking for, so I didn't consider it. – Floris Feb 14 '13 at 20:43
1

If the values in the first column all appear in the second column, and if all you want is replace the values in the second column by 1..n and change the values in the first column accordingly, you can do all of this with a simple call to ismember:

%# define "inputMatrix" here as the first array in your post

[~,newFirstColumn] = ismember(inputMatrix(:,1),inputMatrix(:,2));

To create your output, you'd then write

outputMatrix = [newFirstColumn,(1:length(newFirstColumn))'];
Jonas
  • 74,690
  • 10
  • 137
  • 177
1

If M is the original matrix and R is the renaming matrix, here's how you do it

N = M;

for n = 1:size(M,1)
    N(find(M==R(n,1))) = R(n,2);
end

Note that in this case you're creating a new matrix N with the renamed values. You don't have to do that if you like.

Phonon
  • 12,549
  • 13
  • 64
  • 114