前回の記事でワンショットの剥奪ゲームのトリートメントを作成しました. 同じ被験者にゲームの設定を変えつつ複数回繰り返す方法を考えてみましたが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の特徴」を生かした,便利なパッケージと言えるでしょう.