循环在R

时间:2019-06-27 18:06:09

标签: r loops vectorization

我有一些代码,其中包括for循环和嵌套的if语句。问题是运行时间太长,我想使其更快。

我在名为f2_cebu_davao的数据帧中具有同类群组的数据。此数据框中还有一列称为person_id。同类群组分为3类:“基线”,“其他效果”,“广告系列”。

我想遍历f2_cebu_davao数据框中的每个person_id,并查看其所在的同类群组。如果它在同类群组“基线”或“其他效果”中,那么我将检查before_baseline_othereffects表以查看如果可以在该表中找到该ID。如果可以,我在f2_cebu_davao表中创建一个新列,该值将为“ returning”。否则为“新”。

如果同类群组名称是“ campaign”,我将检查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 :(得分:0)

如果您可以提供一些示例数据和所需的输出,很高兴进行更新和测试。我希望像这样的东西应该可以工作。

我在这里伪造了一些数据:

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. 否则,将“新建”标记为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