避免循环创建data.frame的最有效方法

时间:2016-05-22 20:51:40

标签: r for-loop

我有一个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 
  }
}

4 个答案:

答案 0 :(得分: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)

答案 1 :(得分:1)

不确定这是否更快,

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

答案 2 :(得分:0)

以下是使用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")

答案 3 :(得分:0)

这应该非常快:

## 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中(但矩阵选项当然不会起作用)。