psychopy.org | Reference | Downloads | Github

Randomly sampling without replacement over same distribution multiple times

Hi I am trying to make an experiment such that the duration of one part of the survey (a fixation cross) varies based on a preset distribution, which is list_name= [4,6,2,2,2,4,2,2,4,2,6,10]. I want the duration to sample without replacement (using np.random.choice(list_name, replace=False), but I want the sampling without replacement to reset every 12 trials. So on the 13th trial it will restart with the full list and continue to sample without replacement.

I tried inserting this code into the begin routine part of a code component

if trials.thisN in [0:11]:
    list_name=[4,6,2,2,2,4,2,2,4,2,6,10]
    x_duration=np.random.choice(list_name,replace=False)

However, I keep receiving an error in the code. Does anyone have any suggestions?

Please provide it.

(Can see several things wrong with your code, but is also helpful to know the consequences.)


    if trials.thisN in [0:11]:
                         ^
SyntaxError: invalid syntax

You want a list with two elements, which need to be separated with a comma like this:

if trials.thisN in [0, 11]:
    # create or re-set the list:
    list_name=[4, 6, 2, 2, 2, 4, 2, 2, 4, 2, 6, 10] # not a great variable name

But note that you shouldn’t sample from that list only on those trials: I guess you want a number to be extracted on every trial. In this case, np.random.choice() is not the right approach here. It doesn’t do anything to the list it samples from, so there is no way to prevent getting the same number on a subsequent trial. i.e. the replace=False argument only applies on this single call to the function. e.g. you want five entries, and to guarantee that none are selected more than once. But if you get a later sample of five, then yes, it can easily include entries that were sampled previously, as the list has no memory of any previous sampling. You really should look at the API for functions like these, so you understand what they do, and then can choose the appropriate one: https://docs.scipy.org/doc/numpy-1.13.0/reference/routines.random.html

So a better way to do it is like this:

# only on the first and 12th trials:
if trials.thisN in [0, 11]:
    # create or re-set the list:
    list_name=[4, 6, 2, 2, 2, 4, 2, 2, 4, 2, 6, 10] # not a great variable name
    np.random.shuffle(list_name)

# on every trial, pull a randomly shuffled entry from the list, 
# so it can't be sampled again:
x_duration = list_name.pop()

So I was able to put the code in and there were no errors, but I had psychopy record the jitter duration as a quality check and the numbers did not match the distribution after it hit the 12th trial.

I changed the code slightly, but that should not have affected the results like this right?

if trials.thisN in [0, 11, 23,35,47]:

This was meant to signify that after the 12th, 24th, 36th, and 48th trials the list would start once again drawing without replacement from that pre set list as if no numbers had been removed.
However, after the 12th trial the numbers did not correctly draw from the set distribution. The numbers. It seemed like there was now a new list that was being used for the duration.

Found solution:

if trials.thisN in [0, 12,24,36,48] 

Start after the 12th trial is completed (basically the list is finished) to make the index work. Otherwise the numbers are off.