oTree Forum >

Issue importing variables from CSV

#1 by ckormylo

Hi all. I've tried long and hard to fix this but something strange is happening with my code. 

I am using a CSV file to assign variables for my participants. The game is a 5 round investing game. The CSV file contains variables: MarketID, Treatment1, Treatment2, AssetPrice, SuggestedInvestment. Below is an example of what it looks like. 

MarketID   Treatment1   Treatment 2   AssetPrice   SuggestedInvestment
1           TRUE         TRUE          100          0.48
1           TRUE         TRUE          103          0.43
1           TRUE         TRUE          107          0.47
1           TRUE         TRUE          105          0.45
1           TRUE         TRUE          104          0.44
2           FALSE        TRUE          102          0.48
2           FALSE        TRUE          101          0.47
2           FALSE        TRUE          100          0.43
2           FALSE        TRUE          109          0.40
2           FALSE        TRUE          105          0.49
3           TRUE         FALSE         100          0.48
3           TRUE         FALSE         103          0.43
3           TRUE         FALSE         107          0.47
3           TRUE         FALSE         105          0.45
3           TRUE         FALSE         104          0.44

In the creating session function, I attempt to assign variables in the following way: 

def creating_session(subsession: Subsession):
    import csv
    import random

    f = open(__name__ + '/MarketData.csv')
    reader = list(csv.DictReader(f))

    for player in subsession.get_players():
        participant = player.participant
        
        random_id = random.randint(1, 3)
        filtered_data = [row for row in reader if row['ID'] == str(random_id)]
        
        player.Treatment1= bool(filtered_data[1]['Treatment1'])
        player.Treatment2= bool(filtered_data[1]['Treatment2'])

        for j in range(1, Constants.num_rounds+1):
            exec(f"participant.SuggInv{j} = float(filtered_data[{j-1}]['SuggestedInvestment'])")
            exec(f"participant.AssetPri{j} = float(filtered_data[{j-1}]['AssetPrice'])")
            
For the demo session, I only have 5 participants but for some reason this loop runs 25 times and the Treatment1 and Treatment2 values are always the same (even though their values in the CSV are not). I've tried printing the actual data and the random IDs and they both are distinct every time so I have no idea why the Treatment1 and Treatment2 values are not being assigned properly. I also have no idea why the loop runs so many times when I only have 5 participants. It looks as if it runs Participant*Rounds number of times (5 participants * 5 rounds) so I assume it has something to do with my use of the "exec" method but not sure... Thank you in advance!

#2 by ckormylo

Turns out I just haven't had enough sleep. There were two problems, both completely by oversight. 

First, I forgot to put in if subsession.round_number == 1. Second, my treatment variables were being read as strings making the boolean assignment useless. 

The updated code is below for anyone interested: 

def creating_session(subsession: Subsession):
    if subsession.round_number == 1:
        import csv
        import random

        f = open(__name__ + '/MarketData.csv')
        reader = list(csv.DictReader(f))

        for player in subsession.get_players():
            participant = player.participant
        
            random_id = random.randint(1, 3)
            filtered_data = [row for row in reader if row['ID'] == str(random_id)]
        
            participant.Treatment1= bool(int(filtered_data[1]['Treatment1']))
            participant.Treatment2= bool(int(filtered_data[1]['Treatment2']))
            
            player.Treatment1 = participant.Treatment1
            player.Treatment2 = participant.Treatment2

            for j in range(1, Constants.num_rounds+1):
                exec(f"participant.SuggInv{j} = float(filtered_data[{j-1}]['SuggestedInvestment'])")
                exec(f"participant.AssetPri{j} = float(filtered_data[{j-1}]['AssetPrice'])")
    else:
        # I know I can simplify this by just calling the participant field later in my code when I need to differ things based on treatment but I just haven't done it yet. 
        player.Treatment1 = participant.Treatment1
        player.Treatment2 = participant.Treatment2

Write a reply

Set forum username