Selecting parts of a matrix via indices given by a vector

I have a column vector of the form {1,1,2,3,2,3}t{1,1,2,3,2,3}t\{1, 1, 2, 3, 2, 3\}^t and an associated matrix that has the same number of rows as the column vector, 666, and a number of columns that is equal to the maximum of the values in the vector, 333.

I would like to construct a matrix that has a specific value at the positions {1,1},{2,1},{3,2},{4,3},{5,2},{6,3}\{1, 1\}, \{2, 1\}, \{3, 2\}, \{4,3\}, \{5,2\}, \{6, 3\} and zeroes everywhere else, that is, the row index corresponds to the row index in the column vector and the column index corresponds to the value at that row index.

A solution using a loop is clear to me, is there also a nifty Mathematica trick that does the job?

=================

  

 

Flatten /@ Transpose[{Range@Length@cv, cv}] or Partition[Riffle[Range@Length@cv, Flatten@cv] , 2] where cv is your column vector will give you the desired positions list.
– ciao
Jun 15 ’14 at 21:49

  

 

Thanks for your comment, but note that I do not want to construct a matrix of the form {1,1},{2,1},{3,2},{4,3},{5,2},{6,3}, but a matrix that has a specific value at these positions and the rest zeroes. I edited the question to clarify.
– hps
Jun 15 ’14 at 22:03

  

 

I got that, but since you said nothing about the target matrix (and still really haven’t), I left that to you. Do you mean by “associated” that the target matrix is same # of rows, and has # cols equal to max value of the CV?
– ciao
Jun 15 ’14 at 22:07

  

 

Yes, that would be correct. The “smaller than” part was completely wrong, I edited it out. The target matrix has the dimensions you mention and is filled with zeros.
– hps
Jun 15 ’14 at 22:11

=================

2 Answers
2

=================

(* make some col vec *)
cv = Transpose[{{1, 1, 2, 3, 2, 3}}]

(*Use it to fill positions in associated array with e.g. twos *)
result=Normal@SparseArray[
Flatten /@ Transpose[{Range@Length@#, #}] -> #2, {Length@#, Max@#}] &[cv, 2]

(* {{2, 0, 0}, {2, 0, 0}, {0, 2, 0}, {0, 0, 2}, {0, 2, 0}, {0, 0, 2}} *)

You could also just create the appropriately dimensioned zero array, then use something like ReplacePart to replace desired positions with the value, but I find the SparseArray approach cleaner, and if your arrays are large with mostly zeroes, keeping it sparse (don’t Normal@ it) will save you considerable space to boot…

  

 

Thanks, that is exactly what I was looking for.
– hps
Jun 15 ’14 at 22:12

Another variation using SparseArray:

ClearAll[saF];
saF= SparseArray[MapIndexed[{First@#2, #} &, #1] -> #2, ##3] &

cols = {1, 1, 2, 3, 2, 3};
saF[cols, a] //Normal
(* {{a, 0, 0}, {a, 0, 0}, {0, a, 0}, {0, 0, a}, {0, a, 0}, {0, 0, a}} *)

saF[cols, {a, b, c, d, e, f}] // Normal
(* {{a, 0, 0}, {b, 0, 0}, {0, c, 0}, {0, 0, d}, {0, e, 0}, {0, 0, f}} *)

saF[cols, a, Automatic, b] // Normal
(* {{a, b, b}, {a, b, b}, {b, a, b}, {b, b, a}, {b, a, b}, {b, b, a}} *)

saF[cols, a, {6, 6}] // Normal
(* {{a, 0, 0, 0, 0, 0}, {a, 0, 0, 0, 0, 0}, {0, a, 0, 0, 0, 0},
{0, 0, a, 0, 0, 0}, {0, a, 0, 0, 0, 0}, {0, 0, a, 0, 0, 0}} *)