【问题标题】:Improve slow if else loop in R改进 R 中的 if else 循环
【发布时间】:2016-10-25 14:57:33
【问题描述】:

我在 R 中编写了一个非常简单的代码,但是将它用于超过 2.000.000 行的数据需要将近 2 个小时。

有没有机会改进代码?我希望解决方案尽可能简单。

我的 R 技能还可以(经验

感谢您的帮助。

    system.time(
      for (i in 1:(length(mydata$session_id)-1)){
        if (mydata$session_id[i] != mydata$session_id[i+1]){
          mydata$Einstiegskanal[i]="1"
        } else {
          mydata$Einstiegskanal[i]="0"
        }
      }
    )

    # 6877,1 Seconds = 1,91 h

【问题讨论】:

  • library(dplyr);mydata %>% mutate(Einstiegskanal=ifelse(session_id!=lag(session_id), "1", "0"))

标签: r loops if-statement


【解决方案1】:

看来您所做的只是从一行到下一行的 id 之间的差异。 diff 就是为此而生的。

session_id <- sample(1:10, size = 2000000, replace = TRUE)

system.time({
  ifelse(c(diff(session_id) == 0, NA), "1", "0")
})
   user  system elapsed 
   0.64    0.05    0.69

如果你真的想加快速度,你也可以尝试避开ifelse

你的代码是

lgl <- c(diff(x) == 0, NA)

mydata$Einstiegskanal[!lgl] <- "1"
mydata$Einstiegskanal[lgl] <- "0"

两种方法的速度比较:

library(microbenchmark)
session_id <- sample(1:10, size = 2000000, replace = TRUE)

y <- vector("character", length(session_id))

microbenchmark(
  with_ifelse = ifelse(c(diff(session_id) == 0, NA), "1", "0"),
  avoid_ifelse = {
    lgl <- c(diff(session_id) == 0, NA)
    y[lgl] <- "1"
    y[!lgl] <- "0"
  },
  times = 10)

Unit: milliseconds
         expr       min        lq     mean    median        uq      max neval cld
  with_ifelse 684.69879 686.16912 710.3928 714.88029 726.61384 736.1481    10   b
 avoid_ifelse  88.75335  89.21844  98.8694  90.46677  92.03064 139.8182    10  a 

【讨论】:

  • 非常好!我想用 shift 函数来比较,但这真的很优雅!
【解决方案2】:

你可以试试这样:

mydata <- data.frame(session_id = round(runif(2e6, 0, 10), 0))
mydata2 <- data.frame(session_id = mydata[-1,])
mydata$Einstiegskanal <- c(ifelse(mydata$session_id[1:(nrow(mydata)-1)]==mydata2,1,0), NA)

我将df$Equal 的最后一个值设置为NA,因为这个向量比df 少一个元素。

【讨论】:

    【解决方案3】:

    非常感谢您的回答!

    来自 Benjamin 的以下改编代码非常适合我 :) 与 else if 结合使用的 diff 函数非常聪明,它适用于我的许多 if else 循环。

    system.time({
      mydata$Einstiegskanal<-ifelse(c(diff(mydata$session_id) == 0, NA), "0", "1")
    })
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-01-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-09
      • 1970-01-01
      • 2015-10-28
      相关资源
      最近更新 更多