首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >oTree随机化治疗的有效途径

oTree随机化治疗的有效途径
EN

Stack Overflow用户
提问于 2017-06-24 12:29:19
回答 2查看 1.6K关注 0票数 0

我正在为我将要在我的硕士论文中运行的实验编写代码。我基本上完成了,但我被困在最后一个方面,我找不到解决的方法。我有一个公益游戏,有16个参与者,分成8组两人.我有4种治疗方法,我平衡了比赛。每轮治疗由4名球员进行(他们12岁)。我现在错过的部分是,我希望每个球员都打每一轮准确3次。这种随机化是在下面的代码中执行的,这在理论上是可行的,但实际上我从未设法结束它。在20分钟内,我设法得到了第10轮结束,但无法使程序找到一个组合,以满足上述两个条件的第11和第12轮。我知道这有点棘手,如果你喜欢它更容易理解,但是…你有什么意见建议?非常感谢!

代码语言:javascript
复制
class Subsession(BaseSubsession):

    def before_session_starts(self):
        info_condition = ['Bel', 'Bel', 'Act', 'Act', 'Ctrl', 'Ctrl', 'No', 'No']
        i = 0
        condition = True
        while condition:
            i+= 1
            print('I am in the loop: {} th time. Round{}.'.format(i, self.round_number))
            self.group_randomly()
            for gr_index, g in enumerate(self.get_groups()):
                g.info = info_condition[gr_index]
                for p in g.get_players():
                    p.info_player = g.info

            condition = any(not p.can_go_on(p.info_player) for p in self.get_players())
            if condition == False:
                break
        p.count_treat()
        print('I am out of the loop. Round{}'.format(self.round_number))

class Player(BasePlayer):

    runs = models.CharField()

    def count_treat(self):
        ctrl_count = 0
        no_count = 0
        bel_count = 0
        act_count = 0
        for p in self.in_all_rounds():
            if p.info_player == "Ctrl":
                ctrl_count += 1
            elif p.info_player == "No":
                no_count += 1
            elif p.info_player == "Bel":
                bel_count += 1
            elif p.info_player == "Act":
                act_count += 1
            p.runs = dict()
            p.runs['Ctrl'] = ctrl_count
            p.runs['Bel'] = bel_count
            p.runs['No'] = no_count
            p.runs['Act'] = act_count


    def can_go_on(self, activity):
        self.count_treat()
        print(self.id_in_subsession, self.runs[activity] < 4, activity, self.runs[activity])
        return self.runs[activity] < 4
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-06-26 12:17:10

我决定添加另一个答案,而不是编辑以前的答案,因为第一个答案仍然有帮助,以防您不需要重组组。

假设你有四种治疗方法-- A,B,C,D

有三个条件:

  1. 条件1:玩家从这组中随机处理三轮,然后再进行下一轮(随机)处理三轮等。 我们可以将特定玩家的序列描述为一个列表: AAABBBCCCDDD,其中一个字母对应一个处理,它在这个字符串中的位置对应于一个整数。
  2. 条件2:在每一轮比赛中,都有四名球员玩同样的待遇。
  3. 条件3:改组。这意味着没有球员在所有回合中都有完全相同的治疗顺序。因此,如果有人玩AAABBBCCCDDD,没有人能做到同样的,要成为前三轮A的四个玩家之一,另一个玩家需要有类似AAABBBDDDCCC的东西。

因为人们总是一排排地玩三轮(比如AAA或BBB),那么让我们把三重奏描述为A等等--只是为了简洁起见。所以AAABBBCCCDDD就是ABCD

下面的代码生成一个矩阵12X16,每个玩家连续三次玩每一次处理,并且满足所有的三个条件。

代码远远不是最优的,我相信更有经验的python程序员会很容易地做到这一点----一种提高效率的方法。但很管用。您所需要做的就是将这个矩阵赋值给任何session.vars变量,然后每个玩家都可以根据他的id和整数获得他/她的待遇。

函数by_letters比较两个序列,如果两个序列中至少有一个字母位于同一位置,则返回True。因此,由于True的存在,它返回abcdbdcaFalse,但是返回abcdbadcFalse

我们在一开始就产生了我们四个处理的所有(24)个可能的排列。这是一个我们可以使用的序列池。

函数filtered返回没有重合字母的可用序列的子集(基于by_letters函数)。

当找到治疗的基质时,功能triple只重复三次。

因此,我们通过从我们的治疗集合中产生排列来获得最初的数据。

我们从它中选择一个随机序列,然后根据第一次抽签筛选出剩余的数据。这是我们的第二个序列。

我们找到两个集合的交集,它们都没有与序列1和序列2重合的字母,然后从剩余的子集中画出一条随机线。这是我们的第三个序列。

我们做三组相同的交集来取第四个序列。这是我们4X4的第一个矩阵。我们从初始数据中过滤掉所有的序列(使用itertools.filterfalse),我们使用初始数据循环四次,但是没有我们刚刚发现的序列。

由于不是每次都能找到满足所有条件的4个4X4矩阵,所以我们用try.. except..绘制了另一个随机启动序列。

代码语言:javascript
复制
import random
import itertools
initial_data = list(itertools.permutations('abcd'))

def by_letters(a, b):
    u = zip(a, b)
    for i, j in u:
        if i == j:
            return True
    return False


def filtered(what):
    x = [i for i in a if not by_letters(i, what)]
    return x


def triple(str):
    return ''.join([c+c+c for c in str])

result = None

while result is None:
    try:
        matrices = []
        a = initial_data
        for i in range(4):
            print('cycle:: ', i)
            line1 = random.choice(a)
            line2 = random.choice(filtered(line1))
            s1 = set(filtered(line1))
            s2 = set(filtered(line2))
            sets = [s1, s2]
            line3 = random.choice(list(set.intersection(*sets)))
            s3 = set(filtered(line3))
            sets = [s1, s2, s3]
            line4 = random.choice(list(set.intersection(*sets)))
            matrix1 = [line1, line2, line3, line4]
            matrices.append(matrix1)
            a = list(itertools.filterfalse(lambda x: x in matrix1, a))
        result = matrices                

    except IndexError:
         pass

final = [triple(j) for i in matrices for j in i]
print(final)

输出是这样的:

代码语言:javascript
复制
...
['aaabbbdddccc', 'dddcccaaabbb', 'cccdddbbbaaa', 'bbbaaacccddd', 
'cccdddaaabbb', 'aaabbbcccddd', 'bbbaaadddccc', 'dddcccbbbaaa', 
'aaacccbbbddd', 'dddaaacccbbb', 'cccbbbdddaaa', 'bbbdddaaaccc', 
'dddaaabbbccc', 'bbbdddcccaaa', 'aaacccdddbbb', 'cccbbbaaaddd']
票数 0
EN

Stack Overflow用户

发布于 2017-06-25 13:35:27

我不是百分之百肯定我有这个问题,但是如果我建议任务是在被试内设计中随机化治疗的顺序,那么每个玩家都会玩三次每次治疗,但是这个顺序应该是随机的。那么我认为可以这样做:

models.py

代码语言:javascript
复制
import random
class Constants(BaseConstants):
      treatments = [['Bel', 'Bel','Bel'],
             ['Act', 'Act', 'Act'],
             ['Ctrl', 'Ctrl', 'Ctrl'],
             ['No', 'No', 'No']]

class Subsession(BaseSubsession):
def before_session_starts(self):
    if not self.session.vars.get('treatments'):
        treatments = []
        for g in self.get_groups():
            group_treatments = Constants.treatments
            random.shuffle(group_treatments)
            flat_treatments = [item for sublist in group_treatments for item in sublist]
            if g.id % 2 != 0:
                treatments.append(flat_treatments)
            else:
                treatments.append(treatments[-1])
        self.session.vars['treatments'] = treatments

    for g in self.get_groups():
        g.treatment = self.session.vars['treatments'][g.id - 1][g.round_number - 1]

我们在这里做什么?在Constants中,我们创建了一组包含一系列治疗方法的列表(这不是最优雅的方法,所以如果您需要改变回合的长度,可以使用更多的python方式,但出于懒惰的考虑,它可以工作)。

然后,当每个Subsession启动时,您就会获得这个列表列表,对于每个组,我们会对它们进行洗牌(然后每个子列表中的项不会被重新洗牌),然后使它们变得平坦,所以我们在会话级别将这个经过洗牌的治疗列表添加到一个列表(列表)中只是一个list.After。

因此,在treatments会话变量的第一轮之后,您将为每个组提供一个完整的所有治疗数组。

然后,您只需在treatment模型中设置Group模型字段,该字段等于个性化治疗列表中的项,对应于当前轮和组id。

更新:使两组治疗序列相同。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44736384

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档