psychopy.org | Reference | Downloads | Github

Randomize only parts of a list

OS (e.g. Win10): Win10
PsychoPy version (e.g. 1.84.x): 2020.1.3
Standard Standalone? (y/n) y
What are you trying to achieve?:

I try to randomize a some list positions while keeping the first and last position fixed. This is part of a false memory experiment for a research class. I’d want to present old and new items for recognition. The first item of the recognition list will be the first item of the learn list, then in random order, the second item of the learn list and four new items never presented. The last item of the recognition list is always the topic of the learn list.

What did you try to make it work?:
I tried to create a list at the begining of the experiment

index = ['1','2','3','4','5']

Then at the begining of the routine I shuffle the list, insert the first and the append the last position.

index = shuffle(index)

index.insert(0, '0')
index.append('6')

What specifically went wrong when you tried that?:

    trialList.append(allConds[int(round(ii))])
TypeError: type str doesn't define __round__ method
##### Experiment ended. #####

As you can see my python is really bad. Suggestions was heartly welcome

Cheers Jens

The error seems to be related to ii being a string, not a number. Where does it come from?

I’ve not used insert. Did that bit work?

You can just write shuffle(index) not index=shuffle(index)

index = ['1','2','3','4','5']

This creates a list of one-character strings. If you use a vanilla python shell it becomes more obvious what’s going on. If you’re not used to using python from the terminal, you can for now use an online compiler, like this compiler at Programiz just to try things out. Try this:

index = ['1','2','3','4','5']
first_element = index[0]
print(type(first_element))
# output: <class 'str'>

String objects cannot be used to do numeric operations. What you actually want is:

index = [1,2,3,4,5]

You can see that you now have integers in the list

index = [1,2,3,4,5]
first_element = index[0]
print(type(first_element))
# output: <class 'int'>

Similarly you’ll have to change the method calls where you insert the first/last positions’ elements:

index.insert(0, 0)
index.append(6)

As @wakecarter writes you’ll also have to change this part: index = shuffle(index). The reason is that when you call shuffle(index), the object associated with the variable index is being changed “in place”, meaning that that very object itself is changed. shuffle(x) doesn’t return any value. You can see this if you go again to the Python shell:

foo = shuffle(index)
print(type(foo))
# output: <class 'NoneType'>

The value “passed” to foo is simply None, not a list. So if you do index = shuffle(index), index is “reassigned” to a value of simply None, and your list is destroyed because there is no variable associated with it. This last part might be a bit confusing, so don’t worry too much about the details. Just do shuffle(index) is the point:

from random import shuffle

index = [1,2,3,4,5]
shuffle(index)
index.insert(0, 0)
index.append(6)
print(index)
# output: [0, 4, 3, 2, 5, 1, 6]
# note that the output is of course different each time, since the shuffling is random

Good luck :slight_smile:

Hello,

thanks for the help. Well, this code doesn’t throw an error. However, I might not have inserted it a the proper place (component Abruf). I use the above mentioned code in two place. One, Begin Experiment

index = [1,2,3,4,5]

Second, in Begin Routine

shuffle(index)
index.insert(0, 0)
index.append(6)

However, the loop (TrialsAbruf) that refers to index, only loops over the unshuffled index without the inserted (0) and appended value (6). In addition, the index is not shuffled.

Unbenannt

I moved the code to a component in front of the loop TrialsAbruf. But this did not help. Then much more trials are presented than planned.

It does not matter whether I include

from random import shuffle 

or not.

Still, at the python command prompt everything works as expected.

Cheers Jens

I’m not sure exactly how you want things to work. I’ll give a suggestion that I think will do what you expect. It’s not very beginner-friendly though. So if someone comes up with a more Builder-centric solution (not as heavy on code components) then please describe that.

You want to reuse the same list of “middle numbers” for generating a list of 7 digits, right? What you can do instead of using shuffle is to use the function sample, also from the random module. So with a variable foobar, sample(foobar, len(foobar)) would not shuffle ‘foobar itself’. It would instead return a new list with the same elements as foobar, but in a different order. The len(foobar) part is necessary for telling the sample function how many elements should be sampled from foobar, i. e. as many as there are elements in foobar (so all of them). The code below hopefully helps clear things up.

You also want to make sure that those numbers are used by your Text component. It’s a bit tricky, knowing how to pass values you’re generating yourself to the Text component. I’m not sure what you mean when you say

However, the loop (TrialsAbruf) that refers to index

How is the loop referring to the ‘index’ variable? I don’t know myself how to do that. I’m guessing you might be trying to use the Conditions field of the loop specifications for referring to the index variable, but that doesn’t work unfortunately. The Conditions field expects a file path to e. g. a ‘.csv’ file that has experiment info.

Here’s my suggestion:

The shuffle_numbers routine is responsible for shuffling numbers. The trial routine displays the stimuli. The blank_3000 routine is a 3000ms pause. trial is put inside of a loop that has 7 iterations (one for each digit). The outer loop has as many iterations as you want.

shuffle_numbers only has a code component like this:

trial has a text component:

and a code component:

blank only has a text component:

Lastly, here’s the configuration for the trial_loop

outer_loop has a very similar configuration, only with a different number of reps.

Hello Arboc,

thanks a lot for your help and your very detailed and elaborate response. It pointed me into the proper direction. I placed the code element in the wrong component.

The code element is now in the routine (InstAbruf) preceeding the recognition loop (TrialsAbruf)…

Now, everything gets properly randomized.

Zwischenablage02

With

the loop (TrialsAbruf) that refers to index…

I meant that the following
Zwischenablage01

The list index is used to read specific rows (Selected rows) from an excel file that contains the recogonition items. Now I can finally test the whole experiment.

Cheers Jens

1 Like

Hello,

back again :expressionless:

While the experiment runs loacally when I try to run the experiment on Pavlovia I get an error message.
Zwischenablage02

Index is the list I use to adress rows in an excel file.

index.insert(0,0)

inserts in python an element (0) at a specific position in a list, in my case at the first position of the list. The python code is auto-translated to index.insert in JS. However, searching for ways to insert an element in an array in JS seems to be index.unshift(0). Furthermore, the way to append an element to an array seems to be index.push(x).

Am I am right in assuming that I have to correct the JS-code manually?

Cheers Jens

The auto translate tends to only translate grammar so that kind of thing needs to be translated manually (via switching the component to both or adding something to code_JS)

If you can confirm that .insert(0,x) should be manually translated to .unshift(x) then I’ll add it to my crib sheet, below .pop(0) goes to .shift().

.insert(0,x) translates to .unshift(x).

Cheers Jens

1 Like