【问题标题】:R: match elements between vectors - how to optimaze codeR:匹配向量之间的元素 - 如何优化代码
【发布时间】:2019-12-04 17:30:30
【问题描述】:

让我们想象一下我们有几个人的描述数据框:

des <- c('mad', 'crazy','stupid', 'crazy','wise','dumb','mad','furious')
id <- c(1,2,3,4,5,6,7,8)
d <-data.frame(id,des)
d$dangerous <- NA
dan <-c('mad','crazy','furious')

我们希望将d$des 与向量dan 中的描述相匹配

我准备了以下函数:

for (i in 1:nrow(d)){
  for(j in 1:length(dan)){
    if (d$des[i]==dan[j])
      {d$dangerous[i] <- 1 }
  } }
d
  id     des dangerous
1  1     mad         1
2  2   crazy         1
3  3  stupid        NA
4  4   crazy         1
5  5    wise        NA
6  6    dumb        NA
7  7     mad         1
8  8 furious         1

代码运行良好,但是我想知道如何优化代码,如果它可以处理更长的向量和数据框。有任何想法吗?

【问题讨论】:

    标签: r function optimization vector match


    【解决方案1】:

    以下是几种解决方案和我的一个解决方案的时间安排。
    我已经使用原始 data.frame d 和更大的 data.frame 对函数进行计时,因为 OP 说这是一个优化问题。

    OP <- function(DF, dan){
      DF$dangerous <- NA
      for (i in 1:nrow(DF)){
        for(j in 1:length(dan)){
          if (DF$des[i]==dan[j]) DF$dangerous[i] <- 1
        } 
      }
      DF
    }
    
    Carles <- function(DF, dan){
      DF$dangerous<-ifelse(DF$des %in% dan, 1, NA)
      DF
    }
    
    arg0naut91_1 <- function(DF, dan){
      DF$dangerous <- NA
      transform(DF, dangerous = replace(dangerous, des %in% dan, 1))
    }
    
    arg0naut91_2 <- function(DF, dan){
      DF$dangerous <- NA
      DF$dangerous[DF$des %in% dan] <- 1
      DF
    }
    
    Rui <- function(DF, dan){
      DF$dangerous <- c(1, NA)[(DF$des %in% dan) + 1]
      DF
    }
    
    library(microbenchmark)
    
    mb <- microbenchmark(
      OP = OP(d, dan),
      Carles = Carles(d, dan),
      Rui = Rui(d, dan),
      arg0naut91_1 = arg0naut91_1(d, dan),
      arg0naut91_2 = arg0naut91_2(d, dan)
    )
    print(mb, order = "median")
    #Unit: microseconds
    #         expr     min       lq      mean   median       uq       max neval cld
    #          Rui  22.623  25.1865  82.73746  27.2510  31.6630  5441.491   100  a 
    #       Carles  31.740  34.4120  76.82339  36.9385  42.1760  3753.407   100  a 
    # arg0naut91_2  34.131  36.7140  89.10827  39.5925  46.6930  4577.938   100  a 
    # arg0naut91_1 226.237 230.1020 296.23198 234.6225 243.3040  4847.553   100  a 
    #           OP 757.831 770.1875 926.88995 781.5630 818.2745 10992.040   100   b
    
    
    
    e <- d
    for(i in 1:10) e <- rbind(e, e)
    
    mb2 <- microbenchmark(
      OP = OP(e, dan),
      Carles = Carles(e, dan),
      Rui = Rui(e, dan),
      arg0naut91_1 = arg0naut91_1(e, dan),
      arg0naut91_2 = arg0naut91_2(e, dan),
      times = 10
    )
    print(mb2, order = "median")
    #Unit: microseconds
    #         expr        min         lq        mean      median         uq        max neval cld
    #          Rui    291.090    294.690    346.3638    298.9580    301.238    776.769    10  a 
    # arg0naut91_2    288.123    292.236    312.6684    311.2435    314.495    388.212    10  a 
    #       Carles    427.500    430.120    447.7170    450.2570    453.884    480.424    10  a 
    # arg0naut91_1    513.059    517.822    611.0255    666.7095    670.059    688.023    10  a 
    #           OP 898781.320 909717.469 911988.3906 914269.7245 916975.858 919223.886    10   b
    

    【讨论】:

      【解决方案2】:

      使用ifelse()%in% 可以解决问题:

      d$dangerous<-ifelse(des %in% dan, 1,NA)
      > d
        id     des dangerous
      1  1     mad         1
      2  2   crazy         1
      3  3  stupid        NA
      4  4   crazy         1
      5  5    wise        NA
      6  6    dumb        NA
      7  7     mad         1
      8  8 furious         1
      

      【讨论】:

        【解决方案3】:

        另一种选择:

        transform(d, dangerous = replace(dangerous, des %in% dan, 1))
        
          id     des dangerous
        1  1     mad         1
        2  2   crazy         1
        3  3  stupid        NA
        4  4   crazy         1
        5  5    wise        NA
        6  6    dumb        NA
        7  7     mad         1
        8  8 furious         1
        

        或者:

        d$dangerous[d$des %in% dan] <- 1
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-03-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-11-18
          相关资源
          最近更新 更多