Мышление в векторах с R

Я знаю, что 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 минут. Есть идеи, почему?

Привет, JD, сегодня вечером я наткнулся на этот старый пост. Одно замечание: поместите ваши вызовы c() над циклом, если они не собираются меняться. Каждый цикл вызывает c() 6 раз без необходимости, что оказывается на 600000 дополнительных вызовов функций для c(), чем вам нужно :-)

Vince 27.08.2010 08:22

Можете ли вы поверить, что это было в пределах моих первых нескольких месяцев после того, как я решил действительно начать настоящую работу с R? Я делал несколько простых регрессий и тому подобное ранее, но я решил перенести процедуру стохастического моделирования на R. Это и неловко, и воодушевляет оглядываться назад на мой процесс обучения, задокументированный моими вопросами;) Как и Вирджиния Слим, я пройти долгий путь, детка.

JD Long 27.08.2010 23:45

Хех, поверь мне, это ничего. Есть несколько неловких вопросов, которые я разместил в списках много лет назад. Многое, много больше смущает.

Vince 28.08.2010 04:07
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
26
3
2 711
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Ясно, что я должен был поработать над этим еще час, прежде чем опубликовать свой вопрос. Оглядываясь назад, это так очевидно. :)

Чтобы использовать векторную логику 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 09.09.2009 22:11

@Vince, что такое "анонимные функции"?

Zach 18.03.2011 04:02

Чтобы ответить на ваш вопрос о том, почему цикл из 10000 занял намного больше времени, чем ваш цикл из 1000:

Я думаю, что главным подозреваемым являются конкатенации, которые происходят в каждом цикле. По мере того, как данные становятся длиннее, R, вероятно, копирует каждый элемент вектора в новый вектор, который на один больше. Копирование небольшого (в среднем 500 элементов) набора данных 1000 раз выполняется быстро. Копирование более крупного (в среднем 5000 элементов) набора данных в 10000 раз происходит медленнее.

сегодня я выяснил более быстрый способ добавить элементы в вектор: добавить, чтобы вектор года теперь выглядел как years <-append (years, year, after = length (years))

JD Long 14.01.2009 23:43

Вряд ли это будет намного быстрее - нужно заранее выделить.

hadley 31.07.2009 23:41

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