Выборка из вероятностей, основанных на значениях столбца для большого data.frame

Я не могу найти что-то конкретное для моего вопроса, поэтому я надеюсь, что кто-то может мне помочь. У меня есть фрейм данных (3 миллиона + записей), который содержит три столбца, которые содержат вероятности каждого "события". Таким образом, основным примером для одной записи является вероятность того, что А произойдет 30%, В 20% и С 50%.

Таким образом, в основном каждое наблюдение имеет вероятность быть A, B или C. Эта вероятность зависит от значений в столбцах A, B и C.

Ниже приведен один из способов определения, где он выбирает из столбцов A, B и C, а затем присваивает выборочное значение столбцу "Ответ". НО для 3 миллионов записей это просто не будет работать вообще.

nRowsDf <- nrow(df)
for(i in 1:nRowsDf){
   df[i,c("Answer")] <- sample(sample(c('A','B','C'), size = 1000,
     replace = TRUE, prob = c(df[i,"A_prop"],df[i,"B_prop"], df[i,"C_prop"]))
   ,1)
}

Я уверен, что есть лучший способ, чем поместить его в медленный цикл, который будет работать в течение +-30 часов.

Я тем временем перешел на Excel, не хочу туда идти. Но это то, что я делаю в Excel, с некоторыми изменениями: Как создать случайное значение на основе назначенной вероятности в Excel

2 ответа

Решение

Это R версия метода Excel, на которую вы ссылаетесь, будет обрабатывать ваши данные за четверть секунды - я надеюсь, что это достаточно быстро.

  df$Answer <- with(df, names(df)[1 + rowSums(cbind(A, A+B, A+B+C) < runif(n))])

Оно использует runif генерировать равномерные случайные значения между 0 и 1 и сравнивать их с кумулятивными суммами вероятностей в кадре данных, строка за строкой, точно так же, как это делает решение Excel. Вместо использования cumsum функция в Rтем не менее, примерно в сто раз быстрее (в этом примере) явно вычислить эти суммы с добавлением массива, как показано в вызове cbind,

Я в конечном итоге использовал применить с функцией костюма.

samp <- function(a){  if (sum(a) == 100){
sample(sample(c('A','B',"C"), size = 100, replace = TRUE, prob = c(a)),1)  }  
else{   0  }
}
df$answer <- apply(df[,1:3],1, FUN = samp)

Сделано 3,3 млн. Записей за 2 мин.

Спасибо за помощь, ваш метод работает очень хорошо, но я подумал, что это хорошая возможность узнать больше о функциях применения.

Другие вопросы по тегам