如何在R中加速此循环

如何在R中加速此循环,r,R,我有下面的代码,它读取表的列,如果元素包含正确的字符串,它会在另一个向量中增加相应的值。代码如下: dateArray <- integer(365) for (i in 189500:207097) { if (grepl("Jan", csvaryana[i, "Date"], ignore.case = FALSE, perl = FALSE, fixed = FALSE, useBytes = FALSE)) { for (j in 1:31) {

我有下面的代码,它读取表的列,如果元素包含正确的字符串,它会在另一个向量中增加相应的值。代码如下:

dateArray <- integer(365)

for (i in 189500:207097) {
    if (grepl("Jan", csvaryana[i, "Date"], ignore.case = FALSE, perl = FALSE, fixed = FALSE, useBytes = FALSE)) {
        for (j in 1:31) {
            if (j < 10) {
                if (grepl(paste(sprintf(" 0%d", j), ""), csvaryana[i, "Date"], ignore.case = FALSE, perl = FALSE, fixed = FALSE, useBytes = FALSE))
                    dateArray[j] <- dateArray[j] + 1
                }
            if (grepl(paste(sprintf(" %d", j), ""), csvaryana[i, "Date"], ignore.case = FALSE, perl = FALSE, fixed = FALSE, useBytes = FALSE))
                dateArray[j] <- dateArray[j] + 1
        }
    }
}

dateArray

dateArray不要对
循环使用
,就是这样。有一个非常好的SO帖子讨论了这一点:

答案是要用数据框来加速进程(通过<代码>应用程序>代码>家庭或结帐>代码> PURRR <代码>。清理数据和代码,这样代码> SCAFTF(“0% D”,J)< /代码>不在循环中计算,考虑替换<代码> GRPL < /代码>。 一篇讨论这些概念的好博客文章:
对于
在R中的循环,正如其他答案所解释的那样,速度非常慢。
如果您想加快循环速度,可以阅读本文:

根据本文,您可以执行以下步骤:

  • 使用
    ifesle
    而不是
    if
  • 获取检查循环外部条件(if语句)的语句
  • 仅在真实条件下运行循环
  • 使用which()
  • 使用apply函数族而不是for循环
  • 如果您有多核机器,请使用并行处理
  • 使用消耗更少内存的数据结构
  • <> LI>如果你知道C++,那么最好的方法是使用RCPP,它运行C++代码。
    如果没有一个运行的示例,这是很难做到的。您可以从将循环的每个元素都变成一个函数开始。让我们按如下方式对行进行编号:

    #1  for (i in 189500:207097) {
    #2      if (grepl("Jan", csvaryana[i, "Date"], ignore.case = FALSE, perl = FALSE, fixed = FALSE, useBytes = FALSE)) {
    #3          for (j in 1:31) {
    #4              if (j < 10) {
    #5                  if (grepl(paste(sprintf(" 0%d", j), ""), csvaryana[i, "Date"], ignore.case = FALSE, perl = FALSE, fixed = FALSE, useBytes = FALSE))
    #6                      dateArray[j] <- dateArray[j] + 1
    #7                  }
    #8              if (grepl(paste(sprintf(" %d", j), ""), csvaryana[i, "Date"], ignore.case = FALSE, perl = FALSE, fixed = FALSE, useBytes = FALSE))
    #9                  dateArray[j] <- dateArray[j] + 1
    #10         }
    #11     }
    #12 }
    
    因此,此函数将在函数外部更新
    dateArray
    (无需返回)。我们可以将相同的原理应用于更大的循环(
    i
    ):

    ##检查一月(第2行至第11行)
    
    check.jan我没有循环就解决了这个问题。我将日期列分为年、月、日和时间,所以我只调用count(月和日),它返回一个向量,其中包含每个月和日的频率:

    dateVector <- count(outfile, "X2")
    

    dateVector请给出一个数据的小例子,我们需要看看
    Date
    是如何格式化的。这可能要快得多。很可能会快得多,但除非我们了解数据,否则我们无法给出最佳建议。
    dateArray[as.numeric(format)(strtime)(grep(“Jan”),csvaryana[,,“Date”]、T、value=T)、“%b%d”)、“%d”)]=1
    甚至
    dataArray[as.numeric(gsub(\\d),grep(“Jan”,csvaryana$Date,T,value=T))]=1
    dateArray[as.numeric(gsub(\\d“,”,grep(“Jan”,csvaryana$Date,T,value=T))]=1
    I gues这里应该没有for循环。您可以尝试上面的方法。原始代码似乎只计算1月份每个日期的实例-因此最快和最简单的解决方案可能是将日期列转换为适当的
    date
    数据类型,并使用现有的日期工具(可能使用
    lubridate
    ).像这样手动操作太复杂了。
    ## Update dateArray function (lines 4 to 10)
    update.dateArray <- function(j, i, dateArray, csvaryana) {
        if (j < 10) {
            if (grepl.ifelse(paste(sprintf(" 0%d", j), ""), i, csvaryana)) {
                dateArray[j] <<- dateArray[j] + 1
            }
        } else {
            if (grepl.ifelse(paste(sprintf(" %d", j), ""), i, csvaryana)){
                dateArray[j] <<- dateArray[j] + 1
            }
        }
    }
    
    ## Checking the month of January (lines 2 to 11)
    check.jan <- function(i, dateArray, csvaryana) {
        if(grepl.ifelse("Jan", i, csvaryana)) {
            ## Update dateArray out of the function
            dateArray <<- sapply(1:31, update.dateArray, i, dateArray, csvaryana)
        }
    
        return(dateArray)
    }
    
    dateArray <- integer(365)
    
    ## Running the whole loop
    sapply(189500:207097, check.jan, dateArray, csvaryana)
    ## Updated dateArray
    dateArray
    
    dateVector <- count(outfile, "X2")