Цикл займет слишком много времени, чтобы закончить в R - PullRequest
0 голосов
/ 27 июня 2019

У меня есть некоторый код, который включает цикл for и вложенные операторы if. Проблема в том, что это занимает слишком много времени, и я хочу сделать это намного быстрее.

У меня есть данные о когортах во фрейме данных с именем f2_cebu_davao. В этом фрейме данных также есть столбец с именем person_id. Существует три категории когорт: «Базовая линия», «Другие эффекты», «Кампания».

Я хочу пройтись по каждому person_id в фрейме данных f2_cebu_davao и проверить, в какой он когорте. Если она входит в когорту «Базовая линия» или «Другие эффекты», то я проверю таблицу before_baseline_othereffects, чтобы увидеть если идентификатор можно найти в этой таблице. Если это возможно, я создаю новый столбец в таблице f2_cebu_davao, и значение будет «возвращаться». В противном случае, «новый».

Если имя когорты «кампания», я проверю таблицу before_campaign и выполним ту же процедуру, что и выше.

Мои данные довольно большие (все мои объекты большие), поэтому на их запуск уходит очень много времени (он работает более 30 минут и все еще не завершен!).

Как я могу ускорить это (возможно, используя векторизацию или просто немного изменив код)?

Я пытался сделать цикл, но это занимает слишком много времени.

before_baseline_othereffects <- subset(loans_final_full, submitted_at_date < '2018-05-21')
before_campaign <- subset(loans_final_full, submitted_at_date < '2019-01-21')

for(i in 1:nrow(f2_cebu_davao)){

  if(as.vector(f2_cebu_davao[, 'cohort'][i]) == 'Baseline') {

    if(as.vector(f2_cebu_davao[,'person_id'][i]) %in% as.vector(unique(before_baseline_othereffects$person_id)) == TRUE) {

      f2_cebu_davao$new_or_returning[i] <- 'Returning'

    } else {

      f2_cebu_davao$new_or_returning[i] <- 'New'

    }

  } else if (as.vector(f2_cebu_davao[, 'cohort'][i]) == 'Other Effects'){

     if(as.vector(f2_cebu_davao[,'person_id'][i]) %in% as.vector(unique(before_baseline_othereffects$person_id)) == TRUE) {

      f2_cebu_davao$new_or_returning[i] <- 'Returning'

    } else {

      f2_cebu_davao$new_or_returning[i] <- 'New'

    }



  } else {

    if(as.vector(f2_cebu_davao[,'person_id'][i]) %in% as.vector(unique(before_campaign$person_id)) == TRUE) {

      f2_cebu_davao$new_or_returning[i] <- 'Returning'

    } else {

      f2_cebu_davao$new_or_returning[i] <- 'New'

    }


  }

}

1 Ответ

0 голосов
/ 28 июня 2019

Рад обновить и проверить это, если вы можете предоставить пример данных и желаемый результат.Я ожидаю, что что-то вроде этого должно работать.

Здесь я создаю некоторые поддельные данные:

f2_cebu_davao <- data.frame(stringsAsFactors = F,
  cohort = rep(c("Baseline", "Other Effects", "Something else", 
                 "Another Something"), by = 3),
  person_id = 1:12
)
before_baseline_othereffects <- c(1:4)
before_campaign <- c(5:8)

Здесь я применяю это, используя dplyr case_when, изложив четыре случая.Этот код будет векторизован, и я ожидаю, что он будет работать намного быстрее, чем текущий код цикла.

  1. Когорта - "Базовая линия" или "Другие эффекты", а person_id появляется в before_baseline_othereffects. Это создает«Возвращение» в строках 1 и 2.
  2. Учитывая, что первое условие не было выполнено, но когорта все еще находится в «Базовой линии» или «Другие эффекты», возвращает «Новый», как это делается в строках5 и 6.
  3. Учитывая, что первые два условия не были выполнены, но человек находился в before_campaign, отметьте Returning, как в строках 7 и 8.
  4. В противном случае отметьте New,как в строках 3 и 4 и 9-12.

library(dplyr)
output <- f2_cebu_davao %>%
  mutate(new_or_returning = case_when(
    cohort %in% c("Baseline", "Other Effects") & 
      person_id %in% before_baseline_othereffects ~ "Returning",
    cohort %in% c("Baseline", "Other Effects")    ~ "New",
    person_id %in% before_campaign                ~ "Returning",
    TRUE                                          ~ "New"
  ))

Вот вывод:

> output
              cohort person_id new_or_returning
1           Baseline         1        Returning
2      Other Effects         2        Returning
3     Something else         3              New
4  Another Something         4              New
5           Baseline         5              New
6      Other Effects         6              New
7     Something else         7        Returning
8  Another Something         8        Returning
9           Baseline         9              New
10     Other Effects        10              New
11    Something else        11              New
12 Another Something        12              New
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...