У меня есть набор данных из набора задач дискретного выбора, который включает две альтернативы с тремя атрибутами (бренд, цена, производительность). Из этих данных я взял 1000 ничьих из заднего распределения, которые затем буду использовать для вычисления полезности и, в конечном счете, доли предпочтений для каждого человека и каждой ничьей.
Цена и производительность тестировались на дискретных уровнях (-.2, 0,.2) и (-.25, 0,.25) соответственно. Мне нужно иметь возможность интерполировать полезность между тестируемыми уровнями атрибутов. Предположим теперь, что линейная интерполяция является разумной статистической задачей. Другими словами, какой самый эффективный способ интерполировать полезность цены, если я хочу протестировать сценарий с ценой на 10% ниже? Я не мог придумать гладкий или эффективный способ сделать интерполяцию. Я применил подход mapply() с функцией mdply из plyr
Вот некоторые данные и мой текущий подход:
library(plyr)
#draws from posterior, 2 respondents, 2 draws each
draw <- list(structure(c(-2.403, -2.295, 3.198, 1.378, 0.159, 1.531, 
1.567, -1.716, -4.244, 0.819, -1.121, -0.622, 1.519, 1.731, -1.779, 
2.84), .Dim = c(2L, 8L), .Dimnames = list(NULL, c("brand_1", 
"brand_2", "price_1", "price_2", "price_3", "perf_1", "perf_2", 
"perf_3"))), structure(c(-4.794, -2.147, -1.912, 0.241, 0.084, 
0.31, 0.093, -0.249, 0.054, -0.042, 0.248, -0.737, -1.775, 1.803, 
0.73, -0.505), .Dim = c(2L, 8L), .Dimnames = list(NULL, c("brand_1", 
"brand_2", "price_1", "price_2", "price_3", "perf_1", "perf_2", 
"perf_3")))) 
#define attributes for each brand: brand constant, price, performance
b1 <- c(1, .15, .25)
b2 <- c(2, .1, .2)
#Create data.frame out of attribute lists. Wil use mdply to go through each 
interpolateCombos <- data.frame(xout = c(b1,b2), 
                                atts = rep(c("Brand", "Price", "Performance"), 2),
                                i = rep(1:2, each = 3),
                                stringsAsFactors = FALSE)
#Find point along line. Tried approx(), but too slow
findInt <- function(x1,x2,y1,y2,reqx) {
  range <- x2 - x1
  diff <- reqx - x1
  out <- y1 + ((y2 - y1)/range) * diff
  return(out)
}
calcInterpolate <- function(xout, atts, i){
  if (atts == "Brand") {
    breaks <- 1:2
    cols <- 1:2
  } else if (atts == "Price"){
    breaks <- c(-.2, 0, .2)
    cols <- 3:5
  } else {
    breaks <- c(-.25, 0, .25)
    cols <- 6:8
  }
  utils <- draw[[i]][, cols]
  if (atts == "Brand" | xout %in% breaks){ #Brand can't be interpolated or if level matches a break
    out <- data.frame(out = utils[, match(xout, breaks)])
    } else{ #Must interpolate    
    mi <- min(which(breaks <= xout))
    ma <- max(which(breaks >= xout))
    out <- data.frame(out = findInt(breaks[mi], breaks[ma], utils[, mi], utils[,ma], xout))
    }
  out$draw <- 1:nrow(utils)
  return(out)
}
out <- mdply(interpolateCombos, calcInterpolate)
Чтобы обеспечить контекст того, что я пытаюсь выполнить без интерполирования уровней атрибутов, вот как я это сделаю. Обратите внимание, что бренды теперь определяются с точки зрения ссылки на столбцы. p1 и p2 относятся к определению продукта, u1 и u2 - утилита, а s1, s2 - привилегированные акции для этой ничьей.
Было бы оценено любое толчок в правильном направлении. Мой реальный случай имеет 10 продуктов с 8 атрибутами каждый. В 10-килограммовых ничьих мои 8 гб барана вылезают, но я не могу выбраться из этой кроличьей ямы, которую я сам выкопал.
p1 <- c(1,2,1)
p2 <- c(2,1,2)
FUN <- function(x, p1, p2) {
  bases <- c(0,2,5)
  u1 <- rowSums(x[, bases + p1])
  u2 <- rowSums(x[, bases + p2])
  sumExp <- exp(u1) + exp(u2)
  s1 <- exp(u1) / sumExp
  s2 <- exp(u2) / sumExp
  return(cbind(s1,s2))
}
lapply(draw, FUN, p1 = p1, p2 = p2)
[[1]]
                s1        s2
[1,] 0.00107646039 0.9989235
[2,] 0.00009391749 0.9999061
[[2]]
              s1        s2
[1,] 0.299432858 0.7005671
[2,] 0.004123175 0.9958768