Выборка из вероятностей, основанных на значениях столбца для большого 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 мин.
Спасибо за помощь, ваш метод работает очень хорошо, но я подумал, что это хорошая возможность узнать больше о функциях применения.