psychopy.org | Reference | Downloads | Github

Randomizing a 2x2x2 factorial design

Hi there,

I am trying to program an experiment with a slightly complex design, since it involves 3 factors (factor A, factor B, factor C), each with two levels (levels A1 and A2, levels B1 and B2, and levels C1 and C2), which I’m trying to manipulate independently. Basically this is a 2x2x2 factorial design. However, I would like my design to have the following two constraints:

a) In a total of 8 trials (2x2x2 = 8), I want participants to see all the possible combinations of all three factors once, in a randomized order.

b) To alternate the presentation of the two levels of factor C, so that factor C1 is always followed by C2 (which then is followed by C1 and so on)

My guess is that to achieve this I need to create several nested trials with different condition files (one for every factor?). But then how can I make sure that all three factors are counterbalanced and randomized (a)? And how can I make sure that one of the factors is always alternated (b)?

(I found a post similar to this one here. However, in my case I need to counterbalance using the Excel files.)

Hi @Mardock,

If I got your descriptions correctly, you can use this code in the Begin Experiment Tab to create a condition file.

This condition file satisfies your two constraints:

  1. It randomly presents all combinations of factor levels

  2. However, It shows C1 followed by C2



import pandas as pd
import numpy as np

# define factors and levels
factorA = [1,2]
factorB = [1,2]
factorC= [1,2]
whichC= ['one'] * 2 + ['two'] * 2 + ['three'] * 2 + ['four'] * 2

# create a factoial 2 x 2 x 2 dataframe
trials = pd.DataFrame ([{'factorA':f1, 'factorB':f2, 'factorC':f3} for f1 in factorA for f2 in factorB for f3 in factorC])
trials ['whichC']= np.array(whichC)

# shuffle rows to satisfy your first condition
shuffle_trials = trials.sample(frac=1)

#shuffle rows to alternate factor C levels
shuffle_trials= shuffle_trials.groupby('whichC', sort= False).apply(pd.DataFrame.sort_values, 'factorC', ascending=False)

This code gives you a condition file like this (ignore the whichC column):

Screen Shot 2020-02-16 at 12.24.58 pm

All this code is doing is first, grouping you file based on factor c (whichC) and then sort it.

Finally, you need to add shuffle_trials as your condition file in the loop window. Set the order of the loop presentation as sequential not random.

Hope that helps.

2 Likes

Hi @Omidrezaa.
Thanks. Your solution should in principle work. However, the experiment I am programming uses different condition files for every level in every factor. This is because each level is a not a single number (1 or 2) or file (picture1.jpg or picture2.jpg), but rather a list of numbers. Do you think it would be possible to create the same condition file, but with the names of the Excel files corresponding to each condition?

Thanks again!

Ok. I found a way of doing what I need. I replaced the 1s and 2s for the name of the files. As a result I get this:

This looks good, but for some reason my MOVD_factor (Factor C in the previous example, the one that is supposed to alternate) is repeated in trial 3 (slowMOVD is followed by another slowMOVD). Any idea why this might be happening?

Ok. So I think I’m almost there, but now I’m stuck with my condition files.

In my experiment, each condition file (slow.xlsx, fast.xlsx, close.xlsx, far. xlsx etc) has not only one value, but several, since in each condition I need to update the location of an object differently.
With @Omidrezaa 's help I’ve managed to create a dataframe (shuffle_files) at the beginning of the experiment. The dataframe looks like this:

I then transform this dataframe into a csv file (which I called myStim):
shuffle_trials.to_csv("myStim.csv")

Finally, I added myStim.csv as my condition file in my trial loop. My problems start here: I’m not sure how to tell Psychopy that the conditions file in myStim.csv are not values, but that they are files that it needs to access and then update the location of the object.

When I run my script I get the following error:
ValueError: could not convert string to float: 'smallOTD.xlsx'

Any help would be greatly appreciated! Thanks!

Sorry for my delay in getting back to you.

Not sure if I get what you want, but I think the issue is raised because you assigned the csv name to a variable such as position. Suppose you have a column in the "slow.xlsx" named pos. So, instead of passing the excel file to the position, first read the csv with pandas (as I did in the code above) and call it sth like pos_df and then pass pos_df ["pos"] as the position.