# Sample over a matrix

Assume I have a matrix.

mat = {{1, 1, 8, 3, 5}, {2, 2, 6, 5, 3}, {3, 3, 9, 2, 7}, {4, 4, 7, 1,
7}, {5, 5, 3, 6, 8}, {6, 6, 8, 7, 7}, {7, 7, 2, 4, 4}, {8, 8, 9,
1, 6}, {9, 9, 1, 1, 2}, {10, 10, 2, 1, 6}, {11, 11, 6, 2, 4}, {12,
12, 9, 2, 1}};


I would like to create new matrix that has dimension $12\times3$.

First 2 column is fixed but 3rd column is randomly selected from last 3 column.

First row would be {1, 1, 8} or {1, 1, 3} or {1, 1, 5} Second row would be {2, 2, 6} or {2, 2, 5} or {2, 2, 3}

For example one sample is the following.

sem={{{1, 1, 8}, {2, 2, 3}, {3, 3, 7}, {4, 4, 7}, {5, 5, 6}, {6, 6, 8}, {7, 7, 2}, {8, 8, 6}, {9, 9, 1}, {10, 10, 6}, {11, 11, 6}, {12,12, 9}}} ;


I need say 1000 sample like this. How can I achieve this?

• Why give us a matrix and then say "First row could be..."?? Commented Jan 24, 2018 at 2:15
• @DavidG.Stork Because it wouldn't be nearly as funny if questions would be clearly stated? :) Commented Jan 24, 2018 at 2:22
• ...but waste valuable time and good will... Commented Jan 24, 2018 at 2:28
• Your question is poorly worded. The phrasing of randomly selecting a column implies that within each sample, the third column in that sample comes from the same column from the original matrix. Commented Jan 24, 2018 at 16:32

Create a function that does this for exactly one entry. Then use this function on all your entries:

rand[{x1_, x2_, rest__}] := {x1, x2, RandomChoice[{rest}]};
rand /@ mat
(* {{1, 1, 8}, {2, 2, 5}, {3, 3, 2}, {4, 4, 1}, {5, 5, 8}, {6, 6,
7}, {7, 7, 4}, {8, 8, 6}, {9, 9, 1}, {10, 10, 1}, {11, 11, 2}, {12,
12, 2}} *)


Also

f0 = Extract[#, {{1}, {2}, {RandomInteger[{3, 5}]}}] &;
f0 /@ mat


{{1, 1, 3}, {2, 2, 3}, {3, 3, 2}, {4, 4, 7}, {5, 5, 6}, {6, 6, 7},
{7, 7, 4}, {8, 8, 9}, {9, 9, 1}, {10, 10, 1}, {11, 11, 2}, {12, 12, 2}}

And

f1 = Transpose@Extract[Transpose@#, {{1}, {2}, {RandomInteger[{3, 5}]}}] &;
f1 @ mat


{{1, 1, 5}, {2, 2, 3}, {3, 3, 7}, {4, 4, 7}, {5, 5, 8}, {6, 6, 7},
{7,7, 4}, {8, 8, 6}, {9, 9, 2}, {10, 10, 6}, {11, 11, 4}, {12, 12, 1}}

Here's a faster extractor using a single Extract and single RandomInteger call, although still with a minimally expensive MapIndexed call and a Partition for reshaping:

n = 10000;
mat = RandomInteger[n, {n, n}];

b3extract[mat_] :=
With[{
extractSpec =
Join @@
MapIndexed[
RandomInteger[{3, Length@mat}, Length@mat]
]},
Partition[
Extract[mat, extractSpec],
3
]
];


Here's a timing comparison to the other solutions:

b3extract[mat] // RepeatedTiming // First

0.028

(*halirutan imp*)
rand[{x1_, x2_, rest__}] := {x1, x2, RandomChoice[{rest}]};
rand /@ mat // RepeatedTiming // First

10.5

(*kglr imp 1*)

f0 = Extract[#, {{1}, {2}, {RandomInteger[{3, Length@mat}]}}] &;
f0 /@ mat // RepeatedTiming // First

0.597

(*kglr imp 2*)
f1 = Transpose@
Extract[Transpose@#, {{1}, {2}, {RandomInteger[{3, 5}]}}] &;
f1@mat // RepeatedTiming // First

0.935


And here's a correctness check:

BlockRandom[
SeedRandom[1];
b3extract[mat]
] ==
BlockRandom[
SeedRandom[1];
Extract[#, {{1}, {2}, {RandomInteger[{3, Length@mat}]}}] & /@ mat
]

True


It also scales surprisingly well (well I guess it's still $~O(n^2)$ or worse but with a good pre-factor, probably from most operations being efficiently dispatched to the kernel):

sizes =
{100, 1000, 5000, 10000, 15000, 20000, 25000, 30000, 35000};
timings =
Table[
With[
{
mat = RandomInteger[n, {n, n}]
},
b3extract[mat] // RepeatedTiming // First
],
{n, sizes}
]

{0.00025, 0.0025, 0.014, 0.030, 0.047, 0.10, 0.22, 0.30, 0.40}

fit =
NonlinearModelFit[
prefactor*size^2,
{prefactor},
size
];
fit["BestFit"]

3.2*10^-10 size^2

ListLinePlot[
{