Generating unique random numbers
raponzoni
I am trying to write a procedure that randomly select waves (for the Y axis) and plot them always against the same wave (for the X axis). My problem starts with generating N unique random numbers (integers). I was generating random numbers and saving them as a wave, but I don't know how to search for a number that is in the wave, just to check if it was already selected.
My idea is this:
<br />
(search for a number, eg. 5)<br />
if found <br />
generate another random number<br />
else<br />
save this number<br />
(search for a number, eg. 5)<br />
if found <br />
generate another random number<br />
else<br />
save this number<br />
The problem is that I've searched but couldn't find any command to search for numbers inside a wave.
Cheers
Variable nn
Make/O/N=(nn) W_random
Make/N=(nn)/FREE random=enoise(1)
MakeIndex random, W_random
end
will create a wave called "W_random" containing the integers [0...nn-1] in pseudo-random order.
John Weeks
WaveMetrics, Inc.
support@wavemetrics.com
June 10, 2014 at 09:20 am - Permalink
John Weeks
WaveMetrics, Inc.
support@wavemetrics.com
June 10, 2014 at 09:23 am - Permalink
In my code I can define the random limit by changing the value (this case X) at the function enoise(X).
I tried the same on your code and changed it to 1000, and it still generates random numbers between 0 and NN.
I would like to define the limit, is there any chance to do that in your code?
Ty
June 11, 2014 at 02:22 am - Permalink
June 11, 2014 at 03:33 am - Permalink
(note, you can right click commands inside of IgorPro and get the helpfile!)
The following function is one way to get what you are asking for I believe
Function Random_wave(nn,range)
variable nn,range
variable i
Make/O/N=(nn) W_random
for(i=0; i<nn; i+=1)
// next line makes the range -0.4999 to 0.4999, shifts it to .0001 to 0.9999, and then scales it up to approx. 0 to range
W_random[i] = (enoise(.4999)+0.5)*range
endfor
end
You can add in floor,ceiling,or round commands if you want to output integers instead of decimals, and you could add another layer to call this multiple times if you wanted to make say, 100 such waves, as well as writing in the functionality to have it automatically display the graphs you want.
June 11, 2014 at 05:32 am - Permalink
Yes, the code you wrote is working fine, i just replaced:
W_random[i] = (enoise(.4999)+0.5)*range<br />
for
W_random[i] = (abs(round(range)))<br />
because I need always an integer value and positive!
However, the code has the same problem I have on my own code, it is generating random positive integer values, but not unique values. For exemple, the number 5 could not be in the W_random wave 2 times...
So, my question is, is there any flags to sinalize to generate unique values?
Thanks so much again
June 11, 2014 at 06:13 am - Permalink
June 11, 2014 at 06:23 am - Permalink
Basically, I have around 300 waves where a few should be plotted randomly (with no repetitions). In other words I would like to Igor procedure generate N random plots from those 300 waves.
I need to work with that, almost everyday, so, if I could do a procedure to help me with that my life will be so much easier...
My first idea was generate a wave with the chosen random numbers, then I will find a way to link those numbers with my waves (since they all are numbered on name).
If you have any idea that you think that could be applied here, please share!
Thanks so much
June 11, 2014 at 07:08 am - Permalink
This will work for you I think. Note that (range) must be equal to or greater than (nn). Cant be bothered to code in the check for that:
Function Random_wave(nn,range)
variable nn,range
variable i,target
Make/O/N=(nn) W_random
Make/o/n=(range) W_values = p
for(i=0; i<nn; i+=1)
target = floor((enoise(.4999)+0.5)*(range)) // return a random integer value from 0 to (range - 1)
W_random[i] = W_values[target]
DeletePoints target,1,W_values
range -= 1
endfor
killwaves/z W_values
end
Of course, if you have 300 files and you only need 20 of them randomly selected, you could just use Johnweeks original and much shorter/simpler code, set nn = 300, and then take the first twenty entries.
June 11, 2014 at 08:28 am - Permalink
Just one last issue, linked with the final plotting command. When I type this command at the command line works and the graph is plotted:
Display polyDiff_Y102_map_1 vs xAxis<br />
The final issue is, the name of the wave to be plotted is inside a string. In this exemple VAR="polyDiff_Y102_map_1"
I tryed just replace polyDiff_Y102_map_1 for the variable, but didn't work! Is there any way to refer a wave using a variable?
Thanks so much for the help from you all !
June 11, 2014 at 08:56 am - Permalink
John Weeks
WaveMetrics, Inc.
support@wavemetrics.com
June 11, 2014 at 09:19 am - Permalink
September 7, 2016 at 12:57 pm - Permalink
John Weeks
WaveMetrics, Inc.
support@wavemetrics.com
September 8, 2016 at 09:42 am - Permalink
This is the thread that refuses to die :) Here is a more concise (and perhaps somewhat obscure) method:
variable Nwaves, Nsamples
Make/O/N=(Nwaves) srcWave=p
StatsSample /N=(Nsamples) srcWave
WAVE W_Sampled // created by StatsSample
end
The wave W_Sampled contains your wave indices (random distinct integers) from the number of total waves. If desired, this function could be changed to a wave reference function using the /WAVE flag. Also, the random order of the output indices can easily be sorted if necessary. For details, see
DisplayHelpTopic "StatsSample"
September 13, 2016 at 04:37 am - Permalink