Randomly select every 4 row in condition file

Dear all,

I intend to show participants 3 statements and ask them to rate how much they like the last statement. The problems are disjunctions with 3 premises. For example:
Premise 1: Either the sky is blue or it is white.
Premise 2: The sky is not white.
Conclusion: The sky is blue.
This is what I created in Builder view:


This kind of problem can be logically valid or invalid and can be believable and unbelievable, so making 4 different kind: valid believable, invalid believable, valid unbelievable, invalid unbelievable. So I created 4 different states for each of my affirmative or denial disjunction (look the condition file).

What I now want is to randomly select one of each states as in the following picture:

I want to randomly present one row from every four rows of my conditional file. However, there is one limitation: At the end of the trials, there must be same number of each valid believable, invalid believable, valid unbelievable, invalid unbelievable.

I would appreciate any comment.
Disjunctions.xlsx (16.8 KB)

Hi @Omidrezaa, you could set your trials using a code component at the beginning of a routine, and use the stored variables in the dataframe for each of your textstim. Add the following to a code component in the relevant tabs:

# Begin Experiment
import pandas as pd

dat = pd.read_excel("./Disjunctions.xlsx")
conditionType = [1,2,3,4]  # a list for each type of condition i.e., valid beleiveable, invalid beleivable etc
shuffle(conditionType)

# Begin Routine
trialSet = dat[dat['Type'] == trials.thisN]

if len(conditionType):
    useCondition = conditionType.pop()  # Get condition from shuffled list and remove index from list
else:   
    conditionType = [1,2,3,4]  # If list is empty, create a new one.
    shuffle(conditionType)
    useCondition = conditionType.pop()

thisTrial = trialSet[trialSet['condition']==useCondition]  # This dataframe will contain all variables for your trial

From here, you can define your text in the text components using the following as an e.g.:

$thisTrial['Prem1STD'].values[0]  # Values returns a list, and you index the first value in the list i.e., your sentence - set to change on "Every Repeat"

Important points. Make your nReps in the trial handler == the number of trials, and remove the conditions file as you are no longer using it to randomize your conditions. Also, you will need to amend your conditions file to match the attached randomizeSyn.xlsx (9.4 KB)

Hi @dvbridges.

Thank you for your generous help and useful response. It works nicely. However, there are still some problems. First of all, statements are being presented sequentially, from top of the condition file to the end of it, instead of random presentation. No matter how much I run the program, the order of :types" were 0,1,2,3,4, … This problem arise because we deleted the condition file and I do not know how to set the new condition file to random order.

For the sake of the educational purpose, is it possible if you could explain the code below a little more? I couldn’t make sense of it.

if len(conditionType):
    useCondition = conditionType.pop()  # Get condition from shuffled list and remove index from list
else:   
    conditionType = [1,2,3,4]  # If list is empty, create a new one.
    shuffle(conditionType)
    useCondition = conditionType.pop()

thisTrial = trialSet[trialSet['condition']==useCondition]  # This dataframe will contain all variables for your trial

In addition, I wanted to keep the track of statements and know which “type” and which “condition” is presented and add them to my data. I add these line at the end routine but I could not get what I wanted:

thisExp.addData('ItemType', thisTrial['Conc'].values[0])
thisExp.addData('ItemCond', trialSet['condition'])

And, the last problem: I intend to add some other problems to my experiments such as conditionals and syllogisms which have a similar structure to disjunctions (premise 1, premise 2, conclusion with 4 states of valid believable, invalid believable, etc.). However, the only difference is that, for the disjunctions, I need another randomization:
I need to randomly present one of the two columns below as premise1:

In other words, 50 % of times, premise 1 (Prem1STD) should be presented and for the other 50 % premise 2 (Prem1REV).

Thank you again for all of your generous help.

No problem, @Omidrezaa

Randomise trial order

To randomize order, add the following to the code component:

# Begin Experiment
nTrials = list(range(0, dat['Type'].max()+1))  # Takes max value from Type column and creates a list of trial numbers
shuffle(nTrials)  # shuffles trial numbers to randomize

# Begin Routine - replace first line with
trialSet = dat[dat['Type'] == nTrials[trials.thisN]]  # Uses trialhandler to index random trial number from list

Explanation of code

At the beginning of the experiment, there are 4 conditions from which you would like to present randomly but equally, varying by validity and believability. The conditionType list holds numbers 1 to 4 to index those conditions in the spreadsheet, where 1 = valid beleivable, etc according to your spreadsheet. The loop takes a number from a list of 1 to 4, but does not replace it. So, conditionType.pop() removes one of the conditions from the list for presentation, leaving only 3 other conditions in the list. This continues until the list is empty. The if statement checks whether the list is empty by checking the length of the list. If the list is not empty, a condition is taken from the list using the pop() function. If the list length is 0 or None, then the list is empty and another list must be created, and shuffled so that the conditions are randomized.

Storing data

In the End Routine tab:

thisExp.addData("Validity", thisTrial['Val'].values[0])
thisExp.addData("Believe", thisTrial['Bel'].values[0])
thisExp.addData("Prem1", thisTrial['Prem1STD'].values[0])

Randomisation of columns

Do you want the number of premises per column to be presented an equal number of times across validity and believability conditions, or just random ?

1 Like

Hi @dvbridges.

Vow, It was great. Thank you so much for your all of your help.

Randomise trial order

I add the code that you provided, It does not produce an error, but it does not help. I ran my experiment several times and every time, I was being presented the trials sequentially, as you can see from the “Type” columns of my output:
output

Randomisation of columns

I attached the updated condition file. For the sake of the simplicity, ignore syllogisms. We have two kinds of problems: disjunctions and conditionals, each with two premises and a conclusion. As you can see from the screenshot below, in order to neutralize the effect of the order for premise one, I have a reversed order for that premise (only for disjunction). What I want is that for half of the times, premise one chooses from “Prem1STD” and for the other half, chooses from the column “Prem1REV”. In order to keep conditional safe from any manipulation, both premises for conditional problems are the same.
order

Just one point: As previous, I need each state (Valid believable, etc.) to be presented an equal number of times for disjunctions, and an equal number of times for conditionals, separately.

Thank you again for your time.
Disjunctions.xlsx (11.2 KB)

Ok, because there are so many levels, I think there is a better option to recreate your stimlist at the beginning of every experiment, and go back to using trialhandler for randomisation. This is a better route. Now, this will create a new stimlist called “newList.csv” which you need to add to the loop handler, then you can access all your variables as normal, by the column names. You need to change your conditions file to match the attached randomizeSyn.xlsx (11.4 KB). Note, if pure random is not enough to randomize your prem columns, you will need to find a way to counterbalance across stimuli. Also attached is a quick Builder file which presents text. randomizeSyn_V2.psyexp (7.1 KB) - apologies, I uploaded the wrong Builder file!

In code component:

##### Begin Experiment #####
import pandas as pd
dat = pd.read_excel("./randomizeSyn.xlsx")
# Num is stim type
# Type is subtype, affirm/denial
# condition is validity etc

stimNum = list(range(0, dat['Num'].max()+1))  # Number of stim
conditionType = [1,2,3,4,1,2,3,4]
shuffle(conditionType) 
stimList = pd.DataFrame(columns = list(dat.columns.values))  # Create blank dataframe

for stims in stimNum:
    stim = dat[dat['Num'] == stims]  # Get stim
    aff = stim[stim['Type'] == 0]  # Then get aff stim
    denial = stim[stim['Type'] == 1]  # Then get denial stim
    if len(conditionType):
        # Randomize aff and denial stim by validity condition etc
        stimNum = conditionType.pop()
        stimList = stimList.append(aff[aff['condition'] == stimNum], ignore_index = True)
        stimNum = conditionType.pop()
        stimList = stimList.append(denial[denial['condition'] == stimNum], ignore_index = True)
    if not len(conditionType):
        conditionType = [1,2,3,4,1,2,3,4]
        shuffle(conditionType)

# Save to new dataframe
stimList = pd.DataFrame(stimList)
stimList.to_csv('newList.csv')

##### Begin Routine #builder
# This is where you randomize your columsn
if np.random.random() >.5:
    premText = Prem1STD
    premType = 'STD'
else:
    premText = Prem1REV
    premType = 'REV'

##### End Routine #####
# Save data
thisExp.addData("condition", condition)
thisExp.addData("validity", Val)
thisExp.addData("premText", premText)
thisExp.addData("premType", premType)
 
1 Like

Dear @dvbridges

Thank you so much. It worked nicely. Everything is working as I expected and this is great. I am grateful for codes, which is not only helping me with my task but also teaching me some lessons regarding the coding.

1 Like

Dear @dvbridges

I found a mistake in the codes that you provided. I think I did not clearly explain it. In your last comment, in order to randomize the order of trials, you recommended to recreate the stimlist at the beginning of every experiment and go back to using trialhandler for randomization. But this method does not solve one problem. In NewList.csv that we create every time, the number of valid, believable, invalid and unbelievable are the same, but not according to the subtype. For example, I had 9 valid and 3 invalids for denial subtype. You can see the different portion of each condition in each subtype in the picture below:

From the total of 12 problems in affirmation subtype, 8 of them were valid and only 4 of them are invalid. I think this problem has raised from these two columns of the condition file:
Untitled111

Is there any way to make the number of each condition in each subtype the same?
Thank you for your time in advance.

You need to break the conditionType list into two lists for each type.

AffType = [1,2,3,4]
DenType = [1,2,3,4]
shuffle(AffType) 
shuffle(DenType)
stimList = pd.DataFrame(columns = list(dat.columns.values))  # Create blank dataframe

for stims in stimNum:
    stim = dat[dat['Num'] == stims]  # Get stim
    aff = stim[stim['Type'] == 0]  # Then get aff stim
    denial = stim[stim['Type'] == 1]  # Then get denial stim
    if len(AffType):
        # Randomize aff and denial stim by validity condition etc
        stimNum = AffType.pop()
        stimList = stimList.append(aff[aff['condition'] == stimNum], ignore_index = True)
        stimNum = DenType.pop()
        stimList = stimList.append(denial[denial['condition'] == stimNum], ignore_index = True)
    if not len(AffType):
        AffType = [1,2,3,4]
        DenType = [1,2,3,4]
        shuffle(AffType) 
        shuffle(DenType)
1 Like

Perfect. Thank you again David. It solved the problem.

1 Like