Я знаю, что R наиболее эффективно работает с векторами и следует избегать зацикливания. Мне трудно научиться писать код таким образом. Я хотел бы получить несколько идей о том, как «векторизовать» мой код. Вот пример создания 10-летних выборочных данных для 10000 неуникальных комбинаций состояния (st
), плана1 (p1
) и плана2 (p2
):
st<-NULL
p1<-NULL
p2<-NULL
year<-NULL
i<-0
starttime <- Sys.time()
while (i<10000) {
for (years in seq(1991,2000)) {
st<-c(st,sample(c(12,17,24),1,prob=c(20,30,50)))
p1<-c(p1,sample(c(12,17,24),1,prob=c(20,30,50)))
p2<-c(p2,sample(c(12,17,24),1,prob=c(20,30,50)))
year <-c(year,years)
}
i<-i+1
}
Sys.time() - starttime
Это займет около 8 минут на моем ноутбуке. Я получаю 4 вектора, каждый со 100 000 значений, как и ожидалось. Как я могу сделать это быстрее с помощью векторных функций?
В качестве побочного примечания, если я ограничу приведенный выше код до 1000 циклов на i, это займет всего 2 секунды, но 10000 займет 8 минут. Есть идеи, почему?
Можете ли вы поверить, что это было в пределах моих первых нескольких месяцев после того, как я решил действительно начать настоящую работу с R? Я делал несколько простых регрессий и тому подобное ранее, но я решил перенести процедуру стохастического моделирования на R. Это и неловко, и воодушевляет оглядываться назад на мой процесс обучения, задокументированный моими вопросами;) Как и Вирджиния Слим, я пройти долгий путь, детка.
Хех, поверь мне, это ничего. Есть несколько неловких вопросов, которые я разместил в списках много лет назад. Многое, много больше смущает.
Ясно, что я должен был поработать над этим еще час, прежде чем опубликовать свой вопрос. Оглядываясь назад, это так очевидно. :)
Чтобы использовать векторную логику R, я вынул цикл и заменил его следующим:
st <- sample(c(12,17,24),10000,prob=c(20,30,50),replace=TRUE)
p1 <- sample(c(12,17,24),10000,prob=c(20,30,50),replace=TRUE)
p2 <- sample(c(12,17,24),10000,prob=c(20,30,50),replace=TRUE)
year <- rep(1991:2000,1000)
Теперь я могу сделать 100 000 образцов практически мгновенно. Я знал, что векторы быстрее, но черт возьми. Я предполагаю, что 100000 циклов заняли бы более часа, используя цикл, а векторный подход занимает <1 секунды. Просто ради удовольствия я сделал миллион векторов. На завершение ушло ~ 2 секунды. Поскольку я должен проверить до отказа, я попробовал 10 мм, но на моем ноутбуке 2 ГБ закончилась память. Я переключился на свой рабочий стол Vista 64 с оперативной памятью 6 ГБ и создал векторы длиной 10 мм за 17 секунд. 100 мм заставили все развалиться, поскольку один из векторов был более 763 МБ, что привело к проблеме распределения с R.
Векторы в R для меня удивительно быстрые. Думаю, поэтому я экономист, а не компьютерный ученый.
JD: Изучите do.call, sapply, lapply и tapply. Для меня это были поворотные моменты в R. Анонимные функции тоже полезны.
@Vince, что такое "анонимные функции"?
Чтобы ответить на ваш вопрос о том, почему цикл из 10000 занял намного больше времени, чем ваш цикл из 1000:
Я думаю, что главным подозреваемым являются конкатенации, которые происходят в каждом цикле. По мере того, как данные становятся длиннее, R, вероятно, копирует каждый элемент вектора в новый вектор, который на один больше. Копирование небольшого (в среднем 500 элементов) набора данных 1000 раз выполняется быстро. Копирование более крупного (в среднем 5000 элементов) набора данных в 10000 раз происходит медленнее.
сегодня я выяснил более быстрый способ добавить элементы в вектор: добавить, чтобы вектор года теперь выглядел как years <-append (years, year, after = length (years))
Вряд ли это будет намного быстрее - нужно заранее выделить.
Привет, JD, сегодня вечером я наткнулся на этот старый пост. Одно замечание: поместите ваши вызовы
c()
над циклом, если они не собираются меняться. Каждый цикл вызываетc()
6 раз без необходимости, что оказывается на 600000 дополнительных вызовов функций дляc()
, чем вам нужно :-)