The One with ...

思いついたことや作業メモなどを公開しています

ラウンド毎に異なるパラメータを設定する方法

前回の記事でワンショットの剥奪ゲームのトリートメントを作成しました. 同じ被験者にゲームの設定を変えつつ複数回繰り返す方法を考えてみましたが3日後には忘れそうなので,例によって メモを残しておきます.

グループに共通の値を設定する

結論から言うと,次のコードで一応の目的は達せられます.

class C(BaseConstants):
    NAME_IN_URL = 'relative_deprivation'
    PLAYERS_PER_GROUP = 5
    NUM_ROUNDS = 2
    Rvec = [3,5]#セッション毎に変わるグループ共通の利益率
    nvec = [2,4]#セッション毎に変わるグループ共通の成功者数

class Subsession(BaseSubsession):
    pass

class Group(BaseGroup):
    x = models.IntegerField()
    R = models.IntegerField()#セッション毎に変わるグループ共通の利益率
    PROFIT = models.IntegerField()
    n = models.IntegerField()

def set_parameters(group: Group):#グループオブジェクトを引数にした関数,引数groupのタイプ(クラス)がGroupであることを指定
    group.R = C.Rvec[group.round_number-1]
    group.PROFIT = group.R*100-100
    group.n = C.nvec[group.round_number-1]

class MyWaitPage(WaitPage):
    after_all_players_arrive = set_parameters

このような面倒なコードになる理由は

ズバリ

Conventionally, group-level treatments are assigned in creating_session:

for g in subsession.get_groups():
     g.treatment = random.choice([True, False])

However, this doesn't work when using group_by_arrival_time, because groups are not determined until players arrive at the wait page. (All players are in the same group initially.) Instead, you need to assign treatments in after_all_players_arrive.

だからです.

この実験では行為者の選択前に所与の条件(グループ固定の属性である利益率と成功人数)を、表示する必要があります.条件表示の前にcreating_sessionを使ってグループオブジェクトの属性に値を渡すとエラーがでるというわけです.そこで条件表示の前にafter_all_players_arrive = set_parametersを使ってグループ属性を定義します. (sessionレベルの変数の定義しようと試行錯誤しましたが,うまくいきませんでした).

結局,

  • 定数クラスで水準のベクトルを準備する
  • set_parameters関数を定義し,group属性のround_numberをつかって,ラウンドに対応したパラメータを取得
  • 最初の入力フォーム表示前にwaitpageを追加してafter_all_players_arrive = set_parametersでパラメータをグループの属性に代入

という手順でラウンド毎のパラメータ設定を実行しました.やれやれ.

多少面倒ですが,otreeは「手軽にオブジェクトの属性やメソッドを定義できるPythonの特徴」を生かした,便利なパッケージと言えるでしょう.