【问题标题】:How to speed up sequential analysis in R?如何加快R中的顺序分析?
【发布时间】:2019-10-04 23:01:33
【问题描述】:

我需要在使用之前操作的子结果的同时依次分析数据集。

正如 R 所知,我决定使用它,我尝试的解决方案之一是使用 for 循环。

我循环遍历的数据集有大约 800 万行 4 列。

我使用 data.table 并且变量是字符类型,例如。 “XXXXXXXXX”

我试图循环,但每个周期大约需要 0.7 秒,而“

谁能推荐一个更好的技术。可能是 rcpp、apply 或其他什么?

感谢您的支持,

霍尔格

'%!in%' <- function(x,y)!('%in%'(x,y))
library('data.table')    


dt_loop <- data.table(
              paste0("XXXXXXXXXX", 1:80000000),
              paste0("YXXXXXXXXX", 1:80000000),
              paste0("ZXXXXXXXXX", 1:80000000),
              paste0("AXXXXXXXXX", 1:80000000)
      )

    colnames(dt_loop)[colnames(dt_loop)=="V1"] <- "m"
    colnames(dt_loop)[colnames(dt_loop)=="V2"] <- "c"
    colnames(dt_loop)[colnames(dt_loop)=="V3"] <- "ma"
    colnames(dt_loop)[colnames(dt_loop)=="V4"] <- "unused"


    for(i in 1:nrow(dt_loop)){
      m <- dt_loop$m[i]
      c <- dt_loop$m[i]

      if(m %!in% dt_loop$ma[1:i] & c %!in% dt_loop$ma[1:i]){
        dt_loop$ma[i] <- m
      } else { 
        if(m %in% dt_loop$ma[1:i]){
          dt_loop$ma[i] <- m
        } else {
          dt_loop$ma[i] <- c
        }
      } 
    }

【问题讨论】:

  • 如果您包含一个简单的reproducible example,其中包含可用于测试和验证可能解决方案的示例输入和所需输出,则更容易为您提供帮助。我们不需要全部 800 万行,但我们确实需要一些东西来测试和比较结果。用语言描述你正在尝试做的事情也是一个好主意;可能会有更好的策略。
  • 这段代码似乎从一个数据集开始,其中四列中的任何值都没有重复。然后,对于每一行,我们查看m 是否在ma 中没有出现(它没有),如果cma 中没有出现(它没有)。鉴于此,在该行中将ma 替换为m,然后重复。我预计这将导致所有行的ma 设置为m。我错过了什么?

标签: r performance loops


【解决方案1】:

这是一个自联接笛卡尔积解决方案。我修改了您的代码以获得一些有意义的结果。我还认为,如果您有 800 万行,那么当第 n 个循环依赖于之前的第 n 个循环时,您将遇到性能问题。

数据结构的变化:

  1. 使用sample 在data.table 中获得一些重复
  2. 将列名简化为data.table函数setnames()
  3. 添加了 ID 字段
  4. 删除了未使用的列。
'%!in%' <- function(x,y)!('%in%'(x,y))
library('data.table')    

# Generate Data -----------------------------------------------------------

set.seed(1)
n_rows <- 10
dt_loop <- data.table(
  sample(paste0("X", 1:n_rows), n_rows, replace = T),
  sample(paste0("Y", 1:n_rows), n_rows, replace = T),
  sample(paste0("X", 1:n_rows), n_rows, replace = T)
)

setnames(dt_loop, c('m', 'c', 'ma'))
dt_loop[, ID := .I]

我对您的循环进行了重大更改。

  1. 分配了c &lt;- dt_loop$c[i],因为我不知道在那里使用 m 做了什么。
  2. 删除了第一个 if 语句,因为新分配了 c
# Original loop with Minor Mod --------------------------------------------

for(i in 1:nrow(dt_loop)){
  m <- dt_loop$m[i]
  c <- dt_loop$c[i] #changed to c instead of m

#Removed first ifelse condition
  #as it didn't make sense as originally constructed

  # if(m %!in% dt_loop$ma[1:i] & c %!in% dt_loop$ma[1:i]){
    # dt_loop$ma2[i] <- m
  # } else {
    if(m %in% dt_loop$ma[1:i]){
      dt_loop$ma2[i] <- m
    } else {
      dt_loop$ma2[i] <- c
    }
  # }
}
dt_loop

      m   c  ma ID ma2
 1:  X3  Y3 X10  1  Y3
 2:  X4  Y2  X3  2  Y2
 3:  X6  Y7  X7  3  Y7
 4: X10  Y4  X2  4 X10
 5:  X3  Y8  X3  5  X3
 6:  X9  Y5  X4  6  Y5
 7: X10  Y8  X1  7 X10
 8:  X7 Y10  X4  8  X7
 9:  X7  Y4  X9  9  X7
10:  X1  Y8  X4 10  X1

当我将行数增加到 10,000 时,自联接似乎比循环快,但它仍然变慢。值得注意的是,您可以看到 ma 何时存在重复,因为笛卡尔积扩展了结果,因此您得到 N == 2

我相信有一些方法可以让自我加入工作,这样你就只能获得第 N 行,这应该可以减轻一些压力。

dt_loop[dt_loop
        , on = .(ID <= ID
                 , ma = m)
        , .(.N
            ,i.ma2 #for comparison - remove
            ,ma3 = ifelse(is.na(x.ID), i.c, i.m)
            ,i.ID, i.m, i.c, i.ma
            ,x.ID, x.m, x.c, x.ma 
        )
        , by = .EACHI
        , allow.cartesian = T]

    ID  ma N i.ma2 ma3 i.ID i.m i.c i.ma x.ID  x.m  x.c x.ma
 1:  1  X3 0    Y3  Y3    1  X3  Y3  X10   NA <NA> <NA> <NA>
 2:  2  X4 0    Y2  Y2    2  X4  Y2   X3   NA <NA> <NA> <NA>
 3:  3  X6 0    Y7  Y7    3  X6  Y7   X7   NA <NA> <NA> <NA>
 4:  4 X10 1   X10 X10    4 X10  Y4   X2    1   X3   Y3  X10
 5:  5  X3 2    X3  X3    5  X3  Y8   X3    2   X4   Y2   X3
 6:  5  X3 2    X3  X3    5  X3  Y8   X3    5   X3   Y8   X3
 7:  6  X9 0    Y5  Y5    6  X9  Y5   X4   NA <NA> <NA> <NA>
 8:  7 X10 1   X10 X10    7 X10  Y8   X1    1   X3   Y3  X10
 9:  8  X7 1    X7  X7    8  X7 Y10   X4    3   X6   Y7   X7
10:  9  X7 1    X7  X7    9  X7  Y4   X9    3   X6   Y7   X7
11: 10  X1 1    X1  X1   10  X1  Y8   X4    7  X10   Y8   X1

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-18
    相关资源
    最近更新 更多