是否有更快的方法将逻辑运算应用于R中的大型数据集的子集?

时间:2013-06-24 11:18:42

标签: r optimization subset mclapply

StackOverflow上的第一篇文章,如果我没有得到礼仪,请保持温和。

我有一个大数据框(好吧,实际上有七个,但这并不重要)包含从一副牌中抽出的手。我有另一个与之配合的数组,显示了玩家选择持有的初始牌中的哪些牌。任何未持有的牌都将从牌组中重新抽出。第一个数据框保存所有绘制的卡片,因此每行可以在5到10列之间的任何位置,对于保持在5和0之间的卡片。这有意义吗?例如:

> str(cards01)
'data.frame':   5044033 obs. of  10 variables

> head(cards01)
   V1  V2  V3  V4  V5  V6  V7 V8  structure(c("", "", "", "", "", ""), class = "AsIs")
1  D0 D10  H0  C5  H1  S3  C4 D6                                                      
2  D5 S10  H7  C7  S0  S5 S12 H5                                                      
3  S4  H4  C1  D4 D11  H6  D1                                                         
4  C3  C9  D9 S10  S2  C7  S3 D2                                                      
5 H11  C0  C6  H3 H12 C11  S0                                                         
6 C10  C9 D11  D8  D5  S8

> str(heldCards01)
 num [1:5044033, 1:5] 1 3 1 2 1 1 2 1 1 1 ...
 - attr(*, "dimnames")=List of 2
  ..$ : NULL
  ..$ ..$ : chr [1:5] "1" "2" "3" "4" ...

> head(heldCards01)
     1 2  3  4  5
[1,] 1 3 NA NA NA
[2,] 3 4 NA NA NA
[3,] 1 2  4 NA NA
[4,] 2 3 NA NA NA
[5,] 1 4  5 NA NA
[6,] 1 2  3  4 NA

所以我正在做的是制作一个新的数据框,其中只包含玩家最终得到的卡片,即删除每行中未在持有的卡片阵列中识别的单元格。我已经编写了代码来执行此操作,但现在它已经在整个周末运行但仍未完成。这是我正在运行的代码(这一切都发生在我所拥有的每个数据帧/矩阵对的lapply中,我正在尝试优化的位发生在mclapply中):

all.hands <- lapply(stakes, function(stake){
  cardsOb <- get(paste("cards", stake, sep = ""))
  heldOb <- get(paste("heldCards", stake, sep = ""))
  l <- length(cardsOb[,1])
  mclapply(1:l, function(rowNum) {
    row <- (heldOb[rowNum,])
    theNAs <- as.logical(is.na(row))
    heldIndex <- row[!theNAs]
    discarded <- c(1,2,3,4,5)[-heldIndex]
    if(length(discarded) >= 1) {
      hand <- cardsOb[rowNum,-discarded]
    } else {
      hand <- cardsOb[rowNum,]
    }
    hand <- sort(hand)
  })
})

我是否缺少可以删除某些步骤的功能?如果数据框是一个数组会更快吗?我只需要等待几天了吗?天?我正在使用带有两个Xeon E5-2407四核处理器和32GB内存的Z620上运行。如果重要的话。

1 个答案:

答案 0 :(得分:0)

我是这样做的。 为简单起见,我假设您的初始持卡是在数据帧df1中 保持卡索引是df2(只是更改名称)

这个想法是使用df2行作为匹配df1行的索引,并对所有行重复 为了避免类问题,我使用数组而不是data.frames(这不是很好的索引)

这可以在一个“极客”命令中完成:

holdings = t(sapply(1:nrow(df1),function(x) as.matrix(df1)[x,][as.matrix(df2)[x,]]))

然后,您可以更改行和名称,构建新的data.frame等。

可能有更好的方法可以做到这一点,但我认为上述内容非常简单。随意询问您是否对该命令中的某些内容不了解