【问题标题】:R - Fast subsetting large data table conditioned on a list of data frameR - 以数据框列表为条件的快速子集大数据表
【发布时间】:2015-11-08 09:17:16
【问题描述】:

我有一个数据表和一个数据框列表,格式如下:

require(data.table)
members = c('a','b','c')
DT = do.call('rbind',
         lapply(members, function(x){
             date = seq(as.Date("2015/1/1"), as.Date("2015/12/31"), 'days')
             dummy = sample(length(date))
             dt = data.table(member=sample(x, length(dummy), replace=TRUE), date=date, dummy=dummy)} 
         )
     )

date = seq(as.Date("2015/1/1"), as.Date("2015/12/31"), 'days')
l.members = lapply(members, function(x){
                n.period = sample(10,1)
                do.call('rbind',
                    lapply(1:n.period, function(y){
                        period = sample(date, 2)
                        if (period[1]>period[2]){
                            start=period[2]
                            due=period[1]
                        }else{
                            start=period[1]
                            due=period[2]
                        }
                        return(data.frame(start.date=start, due.date=due))}
                    )
                )
            })
names(l.members) = members

DT 是我想根据l.members 从中提取子集的大型(csv 文件大约 4G)数据表。 l.members 中条目 x 的每个名称都是 unique(DT$member) 中的成员之一。在每个条目中都有一个数据框,每一行代表一个周期 [p1, p2],基于此我想用 @987654327 对 DT 中的行进行子集化@ 是 xDT$date => p1DT$date p2。目前的解决方法如下:

l.member.periods = lapply(members,
                       function(x){
                           DT.member = DT[member==x]
                           apply(l.members[[x]], 1,
                               function(y){
                                   start = y[1]
                                   due = y[2]
                                   return(DT.member[date>=start&date<=due])
                               }
                           )
                        }
                   )

l.members 中大约有 5000 个条目需要几十年的时间,每个条目大多有 10 行(句点)。我尝试用mclapply 替换lapply,但似乎没有用,最终导致内存变干并挂起。我怎样才能加快这个过程?

【问题讨论】:

    标签: r data.table subset large-data


    【解决方案1】:

    您可以使用foverlaps。 首先,您需要将l.members 存储为data.table

    lmembers <- rbindlist(lapply(1:length(l.members), 
                                 function(i)data.table(member=names(l.members)[i], 
                                                       l.members[[i]], 
                                                       keep.rownames = TRUE)))
    
    > head(lmembers)
       member rn start.date   due.date
    1:      a  1 2015-03-30 2015-04-29
    2:      a  2 2015-03-25 2015-12-07
    3:      a  3 2015-02-06 2015-03-01
    4:      a  4 2015-09-19 2015-11-08
    5:      a  5 2015-06-23 2015-08-27
    6:      a  6 2015-04-22 2015-10-08
    

    下一步显然是使用foverlaps

    setkey(lmembers, "member", "start.date", "due.date")
    DT[, date1:=date,]
    setkey(DT, "member","date", "date1")
    lmemberperiods <- foverlaps(lmembers, DT)[, .(member, rn, date, dummy)]
    

    检查这是否会产生预期的结果。

    lmemberperiods[member=="a" & rn==1]
    l.member.periods[[1]][[1]]
    

    【讨论】:

    • 非常感谢,巧妙地使用 type='any' 并附加 date1。
    • 如果我想对每个member 中的每个rn 做某事,推荐的方法是什么?现在我将l.member.periods 拆分为一个成员列表,每个成员都有一个rn 列表,我使用嵌套的lapply 来完成这项工作。也许有更快的方法?
    猜你喜欢
    • 2015-12-21
    • 2021-12-16
    • 1970-01-01
    • 1970-01-01
    • 2014-02-20
    • 2021-08-01
    • 1970-01-01
    • 2012-11-18
    • 1970-01-01
    相关资源
    最近更新 更多