Случайный выбор сбалансированных экспериментальных проектов

Я пишу код для создания сбалансированных экспериментальных планов для исследования рынка, особенно для использования в совместном анализе и масштабировании максимальной разницы.

Первым шагом является создание частично сбалансированного Незавершенный блок (PBIB) дизайн. Это просто сделать с помощью пакета R AlgDesign .

Для большинства типов исследований такой конструкции будет достаточно. Однако в маркетинговых исследованиях необходимо контролировать влияние ордеров в каждом блоке. Здесь я был бы признателен за помощь.

Создание тестовых данных

# The following code is not essential in understanding the problem, 
# but I provide it in case you are curious about the origin of the data itself.
#library(AlgDesign)
#set.seed(12345)
#choices <- 4
#nAttributes <- 7
#blocksize <- 7
#bsize <- rep(choices, blocksize)
#PBIB <- optBlock(~., withinData=factor(1:nAttributes), blocksizes=bsize)
#df <- data.frame(t(array(PBIB$rows, dim=c(choices, blocksize))))
#colnames(df) <- paste("Item", 1:choices, sep="")
#rownames(df) <- paste("Set", 1:nAttributes, sep="")

df <- structure(list(
  Item1 = c(1, 2, 1, 3, 1, 1, 2), 
  Item2 = c(4, 4, 2, 5, 3, 2, 3), 
  Item3 = c(5, 6, 5, 6, 4, 3, 4), 
  Item4 = c(7, 7, 6, 7, 6, 7, 5)), 
  .Names = c("Item1", "Item2", "Item3", "Item4"), 
  row.names = c("Set1", "Set2", "Set3", "Set4", "Set5", "Set6", "Set7"), 
  class = "data.frame")

** Определение двух вспомогательных функций

balanceMatrix вычисляет баланс матрицы:

balanceMatrix <- function(x){
    t(sapply(unique(unlist(x)), function(i)colSums(x==i)))
}

balanceScore вычисляет метрику ' fit '- чем меньше баллов, тем лучше, без идеального нуля:

balanceScore <- function(x){
    sum((1-x)^2)
}

Определите функцию, которая произвольно изменяет выборку строк

findBalance <- function(x, nrepeat=100){
    df <- x
    minw <- Inf
    for (n in 1:nrepeat){
        for (i in 1:nrow(x)){df[i,] <- sample(df[i, ])}
        w <- balanceMatrix(df)
        sumw <- balanceScore(w)
        if(sumw < minw){
            dfbest <- df
            minw <- sumw
        }
    }
    dfbest
}

Основной код

Фрейм данных df представляет собой сбалансированный дизайн из 7 наборов. В каждом наборе респонденту будет отображаться 4 предмета. Числовые значения в df относятся к 7 различным атрибутам. Например, в наборе 1 респонденту будет предложено выбрать предпочтительный вариант из атрибутов 1, 3, 4 и 7.

Порядок пунктов в каждом наборе концептуально не важен. Таким образом, порядок (1,4,5,7) идентичен (7,5,4,1).

Однако, чтобы получить полностью сбалансированный дизайн, каждый атрибут будет появляться равное количество раз в каждом столбце. Этот дизайн несбалансирован, поскольку атрибут 1 появляется 4 раза в столбце 1:

df

     Item1 Item2 Item3 Item4
Set1     1     4     5     7
Set2     2     4     6     7
Set3     1     2     5     6
Set4     3     5     6     7
Set5     1     3     4     6
Set6     1     2     3     7
Set7     2     3     4     5

Чтобы попытаться найти более сбалансированный дизайн, я написал функцию findBalance . Таким образом выполняется случайный поиск лучших решений путем случайной выборки по строкам df . При 100 повторах он находит следующее лучшее решение:

set.seed(12345)
dfbest <- findBalance(df, nrepeat=100)
dfbest

     Item1 Item2 Item3 Item4
Set1     7     5     1     4
Set2     6     7     4     2
Set3     2     1     5     6
Set4     5     6     7     3
Set5     3     1     6     4
Set6     7     2     3     1
Set7     4     3     2     5

Это выглядит более сбалансированным, и вычисленная матрица баланса содержит множество единиц. Матрица баланса подсчитывает, сколько раз каждый атрибут появляется в каждом столбце. Например, в следующей таблице указано (в верхней левой ячейке), что атрибут 1 дважды появляется совсем не в столбце 1, а дважды в столбце 2:

balanceMatrix(dfbest)

     Item1 Item2 Item3 Item4
[1,]     0     2     1     1
[2,]     1     1     1     1
[3,]     1     1     1     1
[4,]     1     0     1     2
[5,]     1     1     1     1
[6,]     1     1     1     1
[7,]     2     1     1     0

Балансовая оценка для этого решения равна 6 , указывает, что есть по крайней мере шесть ячеек, не равных 1:

balanceScore(balanceMatrix(dfbest))
[1] 6

Мой вопрос

Спасибо, что вы последовали этому подробному примеру. У меня вопрос, как я могу переписать эту функцию поиска, чтобы она была более систематической? Я хотел бы сообщить R:

  • Свернуть balanceScore (df)
  • Путем изменения порядка строк df
  • Subject to: уже полностью ограничено
12
задан Andrie 12 April 2011 в 18:57
поделиться