I'm trying to write a program that takes a given matrix A of 1's and 0's and flips a designated amount of 1's to -1's.

lis1 = ArrayRules[A];
For[i = 1, i < Length[lis1] , i++
   lis2 = RandomChoice[ArrayRules[A], n];
 {a, b} = lis2[[i]];
ReplacePart[lis1, {a,b} -> -1];

This obviously doesn't work, and I'm not sure I even need the For loop for this, but what syntax do I need specifically to replace the [i,j] element of lis1 with -[i,j] of lis2?
Is there a more efficient way of doing this?

  • $\begingroup$ ReplacePart[list1, {##} -> -list2[[##]]] & @@@ {{i1, j1}, {i2, j2}} ? $\endgroup$ – Algohi Jan 26 '16 at 2:49

Here's a quick helper function to do so. It first finds the position of each $1$ in the original matrix using Position; it then selects $n$ of these positions randomly using RandomSample and replaces their value with $-1$ using ReplacePart:

flipsome[matrix_?MatrixQ, n_Integer] :=
 ReplacePart[matrix, RandomSample[Position[matrix, 1], n] -> -1]

Let's generate a random matrix of ones and zeros:

(a = RandomInteger[{0, 1}, {10, 10}]) // MatrixForm

Mathematica graphics

.. and use flipsome to flip 10 randomly selected $1$s to $-1$:

flipsome[a, 10] // MatrixForm

Mathematica graphics

  • $\begingroup$ I'm getting the error ""RandomSample cannot generate a sample of length 2, which is greater \ than the length of the sample set {}. If you want a choice of \ possibly repeated elements from the set, use RandomChoice"" when I try to flip 2 elements, any suggestions? $\endgroup$ – TeeJay Jan 26 '16 at 4:01
  • $\begingroup$ Position[matrix, 1] seems to be the problem. I can fix it by substituting Normal[matrix] for matrix, but this is pretty inefficient. I can't figure out how to do this with ArrayRules[matrix]. $\endgroup$ – TeeJay Jan 26 '16 at 4:05
  • $\begingroup$ @TeeJay That seems to indicate that you are applying flipsome to an array that does not actually contain any $1$s, so Position returns an empty list. $\endgroup$ – MarcoB Jan 26 '16 at 4:05


flipF = MapAt[-1 &, #, RandomSample[Position[#, 1], #2]] &;
(* or *) flipF = MapAt[-1 &, #, RandomSample[SparseArray[#]["NonzeroPositions"], #2]] &

a = RandomInteger[{0, 1}, {9, 9}];
Row[Labeled[MatrixForm@ToExpression@#, #, Top] & /@ {"a", "flipF[a,5]"}, Spacer[5]] 

Mathematica graphics


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.