I have an array of integers/indices (i.e. arr_F_idx = np.arange(0,200)) and I would like to draw 100 pairs without repetition. I am using a masked array (I transform arr_F_idx after the first draw, as shown in the code below), but it seems that numpy.random.choice still draws the masked elements.
arr_F_idx = np.arange(0,200)
draw = np.random.choice(arr_F_idx,2,replace=False)
arr2_Drawn_pairs[0,0] = draw[0]
arr2_Drawn_pairs[0,1] = draw[1]
arr_F_idx_dum1 = np.array(arr_F_idx == draw[0])
arr_F_idx = np.ma.array(arr_F_idx, mask = arr_F_idx_dum1)
arr_F_idx_dum2 = np.array(arr_F_idx == draw[1])
arr_F_idx = np.ma.array(arr_F_idx, mask = arr_F_idx_dum2)
for i in range(1,100):
draw = np.random.choice(arr_F_idx,2,replace=False)
arr2_Drawn_pairs[i,0] = draw[0]
arr2_Drawn_pairs[i,1] = draw[1]
arr_F_idx_dum1 = np.array(arr_F_idx == draw[0])
arr_F_idx = np.ma.array(arr_F_idx, mask = arr_F_idx_dum1)
arr_F_idx_dum2 = np.array(arr_F_idx == draw[1])
arr_F_idx = np.ma.array(arr_F_idx, mask = arr_F_idx_dum2)
The (sample) output that I get is
arr_F_idx
masked_array(data=[--, --, --, --, 4, 5, --, --, --, --, --, 11, 12, 13,
--, --, 16, 17, --, 19, --, 21, 22, --, 24, --, --, --,
28, --, --, --, 32, 33, 34, --, --, 37, 38, 39, --, 41,
--, --, --, --, --, --, 48, --, --, --, --, --, --, --,
--, 57, 58, --, 60, --, --, 63, 64, --, --, --, --, --,
--, --, --, 73, --, --, 76, --, 78, --, --, --, --, --,
--, --, --, --, 88, 89, --, --, 92, --, --, --, --, --,
98, 99, --, 101, 102, --, --, --, 106, --, --, --, --,
111, --, --, --, --, 116, --, --, --, --, 121, --, 123,
124, 125, --, 127, --, --, --, 131, --, --, --, 135,
--, --, --, --, --, 141, --, --, --, --, --, --, --,
--, --, 151, --, --, --, 155, --, --, --, 159, --, 161,
--, --, --, 165, --, 167, --, 169, --, 171, --, --, --,
--, 176, --, 178, 179, --, --, --, 183, --, 185, --,
--, --, 189, 190, --, --, 193, 194, --, 196, --, 198,
199],
mask=[ True, True, True, True, False, False, True, True,
True, True, True, False, False, False, True, True,
False, False, True, False, True, False, False, True,
False, True, True, True, False, True, True, True,
False, False, False, True, True, False, False, False,
True, False, True, True, True, True, True, True,
False, True, True, True, True, True, True, True,
True, False, False, True, False, True, True, False,
False, True, True, True, True, True, True, True,
True, False, True, True, False, True, False, True,
True, True, True, True, True, True, True, True,
False, False, True, True, False, True, True, True,
True, True, False, False, True, False, False, True,
True, True, False, True, True, True, True, False,
True, True, True, True, False, True, True, True,
True, False, True, False, False, False, True, False,
True, True, True, False, True, True, True, False,
True, True, True, True, True, False, True, True,
True, True, True, True, True, True, True, False,
True, True, True, False, True, True, True, False,
True, False, True, True, True, False, True, False,
True, False, True, False, True, True, True, True,
False, True, False, False, True, True, True, False,
True, False, True, True, True, False, False, True,
True, False, False, True, False, True, False, False],
fill_value=999999)
For smaller ranges it happens as well; of course for very small ranges this is not a problem, but as I have mentioned, I want to exhaust the original array to the point that all its elements will be masked. The problem seems to be that the np.random.choice somehow still draws the masked elements, even though it is not supposed to (otherwise I do not see the point of the object called masked array). I may be doing something wrong. I will appreciate help on this issue, also if there is a simpler way to make the draws of pairs without repetition across and within pairs.
Edit: In fact, the numpy random.choice draws masked elements, as can be seen in the output (e.g. number 177 is drawn twice and 191 three times):
arr2_Drawn_pairs
Out[53]:
array([[ 20., 49.],
[ 35., 114.],
[ 44., 42.],
[ 52., 140.],
[191., 59.], 191 - the first time
[147., 144.],
[ 74., 143.],
[ 23., 43.],
[130., 1.],
[146., 166.],
[ 62., 80.],
[ 26., 138.],
[152., 71.],
[ 50., 87.],
[ 69., 9.],
[ 20., 65.],
[ 3., 162.],
[ 30., 104.],
[168., 145.],
[154., 54.],
[129., 2.],
[ 79., 170.],
[ 14., 188.],
[107., 30.],
[119., 188.],
[139., 94.],
[132., 158.],
[ 0., 69.],
[ 47., 27.],
[192., 72.],
[181., 160.],
[ 95., 162.],
[ 40., 25.],
[107., 8.],
[128., 10.],
[ 7., 83.],
[ 91., 173.],
[174., 10.],
[134., 82.],
[ 67., 52.],
[195., 172.],
[197., 96.],
[ 15., 188.],
[184., 164.],
[ 18., 180.],
[ 45., 27.],
[ 86., 84.],
[ 97., 128.],
[149., 6.],
[109., 85.],
[182., 62.],
[ 53., 68.],
[157., 81.],
[188., 25.],
[107., 45.],
[117., 86.],
[195., 47.],
[105., 103.],
[ 51., 162.],
[187., 162.],
[ 70., 97.],
[ 29., 156.],
[175., 177.],
[ 0., 10.],
[ 87., 46.],
[ 1., 119.],
[ 93., 90.],
[174., 53.],
[ 77., 84.],
[ 84., 66.],
[ 91., 186.],
[ 83., 59.],
[137., 140.],
[136., 186.],
[100., 195.],
[173., 81.],
[120., 115.],
[ 36., 46.],
[112., 148.],
[118., 103.],
[ 8., 128.],
[ 56., 65.],
[158., 145.],
[180., 122.],
[142., 126.],
[133., 45.],
[ 59., 173.],
[110., 119.],
[177., 31.], 177 - the first time!
[ 82., 158.],
[ 53., 113.],
[ 85., 150.],
[126., 94.],
[ 61., 152.],
[ 93., 40.],
[ 1., 55.],
[ 96., 162.],
[153., 108.],
[163., 9.],
[ 75., 50.],
[101., 47.],
[178., 148.],
[188., 183.],
[ 69., 177.], 177 - the second time!
[141., 16.],
[ 31., 28.],
[106., 147.],
[ 66., 176.],
[156., 96.],
[ 9., 21.],
[139., 57.],
[106., 11.],
[ 25., 2.],
[152., 69.],
[ 34., 169.],
[148., 191.], 191 - the second time!
[105., 32.],
[187., 156.],
[105., 191.], 191 - the third time!
[ 53., 128.],
[ 56., 30.],
[176., 7.],
[168., 150.],
[ 48., 101.],
[105., 167.]])
Edit 2: A brute-force method for obtaining my desired result is perhaps creating a new array to sample from after every draw,
arr_F_idx_iter = np.append(arr_F_idx[0:draw[0]],arr_F_idx[draw[0]+1:199])
but I think the question of whether this can be done efficiently with masked arrays is still legitimate, as it would be quicker, maybe also points out a flaw in how masked arrays work.