【问题标题】:Most efficient way of avoiding loops to create data.frame避免循环创建 data.frame 的最有效方法
【发布时间】:2016-05-23 07:30:41
【问题描述】:

我有一个 data.frame,其中包含棒球比赛每局得分的得分作为特征向量。

我想创建一个新的 data.frame,其中列出了每场比赛的每局得分。我可以用一个循环来做到这一点,但我知道这对于任何合理数量的观察来说都太慢了,而且显示的rbind 方法也不理想。

局数可能会有所不同,x 表示球队不需要在第 9 局中击球,因为比赛已经获胜。

library(stringr)

data <- data.frame(gameID=c("a","b","c"),innings=c("002100000","30000000x","10101010101"))

for(i in 1:nrow(data)) {
  box <- as.integer(str_split(data$innings[i], "")[[1]])

  tempdf <- data.frame(box,id=data$gameID[i])

  if(i!=1) {
    df <- rbind(df,tempdf)
  } else {
    df <- tempdf 
  }
}

【问题讨论】:

    标签: r for-loop


    【解决方案1】:

    这有点帮助(30%):

    res <- vector("list", nrow(data))
    for(i in seq_along(res))
      res[[i]] <- data.frame(box=as.integer(str_split(data$innings[i], "")[[1]]),
                             id=data$gameID[i])
    do.call(rbind, res)
    

    【讨论】:

      【解决方案2】:

      不确定这是否更快,

      library(splitstackshape)
      data$innings <- gsub('', ' ', data$innings)
      cSplit(data, 'innings', ' ', 'long')
      

      【讨论】:

        【解决方案3】:

        这是一种使用lapply 列表的方法:

        library(dplyr)  # for bind_rows -- you can also use do.call(rbind, list)
        innings <- str_split(data$innings, "")
        names(innings) <- data$gameID
        innings <- lapply(innings, function(x) data.frame(box = x))
        bind_rows(innings, .id = "id")
        

        【讨论】:

        • 比我的解决方案快两倍 :o)
        • 应用于一些真实数据时比原始数据快 8 倍以上
        【解决方案4】:

        这应该很快:

        ## Defined these separately just for readability
        innings <- as.character(data$innings)  # or use 'stringsAsFactors=FALSE' when defining the data frame
        box <- unlist(strsplit(innings, ""))
        id <- rep(data$gameID, nchar(innings))
        
        ## To get a character matrix back
        cbind(box, id)
        
        ## To get a data frame back
        data.frame(box=box, id=id, stringsAsFactors=FALSE)
        

        使用矩阵更快,但如果您想要混合类使用数据框。此外,对于数据框,使用字符比使用因子更快(因此使用 stringsAsFactors=FALSE 参数)。如果您希望 box 是数字,您可以将其包装在 as.integer 中(当然,矩阵选项将不起作用)。

        【讨论】:

          猜你喜欢
          • 2017-09-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-08-22
          • 2020-07-06
          • 2018-11-25
          • 1970-01-01
          相关资源
          最近更新 更多