5
$\begingroup$

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?

$\endgroup$
  • $\begingroup$ Why give us a matrix and then say "First row could be..."?? $\endgroup$ – David G. Stork Jan 24 '18 at 2:15
  • $\begingroup$ @DavidG.Stork Because it wouldn't be nearly as funny if questions would be clearly stated? :) $\endgroup$ – halirutan Jan 24 '18 at 2:22
  • $\begingroup$ ...but waste valuable time and good will... $\endgroup$ – David G. Stork Jan 24 '18 at 2:28
  • $\begingroup$ 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. $\endgroup$ – Acccumulation Jan 24 '18 at 16:32
8
$\begingroup$

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}} *)
$\endgroup$
7
$\begingroup$

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}}

$\endgroup$
6
$\begingroup$

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[
       Thread[{#2[[1]], {1, 2, #}}] &,
       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[
   Thread[{sizes, timings}],
   prefactor*size^2,
   {prefactor},
   size
   ];
fit["BestFit"]

3.2*10^-10 size^2

ListLinePlot[
 {
  Thread[{sizes, timings}],
  Map[{#, fit["BestFit"] /. size -> #} &, sizes]
  }
 ]

asdasd

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.