如何在极大的数据帧中优化循环

时间:2013-10-06 19:11:45

标签: r

我有一个数据框“x”,包含590万行和4列:idnumber / integer,compdate / integer和judge / character,代表在行政法院完成的个案。数据是从stata数据集导入的,日期字段是整数,这对我来说很好。我想通过计算法官在相关案件完成日期的30天窗口内完成的案件数量来创建案件量变量。

这是前34行数据:

idnumber    compdate    judge
1   9615    JVC
2   15316   BAN
3   15887   WLA
4   11968   WFN
5   15001   CLR
6   13914   IEB
7   14760   HSD
8   11063   RJD
9   10948   PPL
10  16502   BAN
11  15391   WCP
12  14587   LRD
13  10672   RTG
14  11864   JCW
15  15071   GMR
16  15082   PAM
17  11697   DLK
18  10660   ADP
19  13284   ECC
20  13052   JWR
21  15987   MAK
22  10105   HEA
23  14298   CLR
24  18154   MMT
25  10392   HEA
26  10157   ERH
27  9188    RBR
28  12173   JCW
29  10234   PAR
30  10437   ADP
31  11347   RDW
32  14032   JTZ
33  11876   AMC
34  11470   AMC

这就是我想出的。因此,对于每个记录,我正在为该特定判断获取数据的子集,然后对在30天窗口中确定的情况进行子集化,然后将子集化数据帧中的向量长度分配给主题案例的caseload变量,如下:

for(i in 1:length(x$idnumber)){
  e<-x$compdate[i]
  f<-e-29
  a<-x[x$judge==x$judge[i] & !is.na(x$compdate),]
  b<-a[a$compdate<=e & a$compdate>=f,]
  x$caseload[i]<-length(b$idnumber)
}

它正在运作,但需要很长时间才能完成。如何优化此功能或更轻松地执行此操作。对不起,我对r和编程都很陌生 - 我是一名法学教授,试图分析法庭数据......我的帮助表示赞赏。谢谢。 肯

2 个答案:

答案 0 :(得分:3)

您不必遍历每一行。您可以立即对整个列执行操作。首先,创建一些数据:

# Create some data.
n<-6e6 # cases
judges<-apply(combn(LETTERS,3),2,paste0,collapse='') # About 2600 judges
set.seed(1)
x<-data.frame(idnumber=1:n,judge=sample(judges,n,replace=TRUE),compdate=Sys.Date()+round(runif(n,1,120)))

现在,您可以创建一个滚动窗口函数,并在每个裁判上运行它。

# Sort
x<-x[order(x$judge,x$compdate),]
# Create a little rolling window function.
rolling.window<-function(y,window=30) seq_along(y) - findInterval(y-window,y)
# Run the little function on each judge.
x$workload<-unlist(by(x$compdate,x$judge,rolling.window)))

答案 1 :(得分:2)

我对滚动计算没有多少经验,但是......

  • 每天计算一次,而不是按个案计算(因为同一天的情况会相同)。
  • 计算案例数量的累积总和,然后获取此总和的当前值与31天前的总和值(或min{daysAgo:daysAgo>30},因为案例未每天都得到解决)的差异。

使用data.table可能是最快的。这是我使用@nograpes模拟数据的尝试。评论以#开头。

require(data.table)
DT <- data.table(x)
DT[,compdate:=as.integer(compdate)]
setkey(DT,judge,compdate)

# count cases for each day
ldt <- DT[,.N,by='judge,compdate']
# cumulative sum of counts
ldt[,nrun:=cumsum(N),by=judge]
# see how far to look back
ldt[,lookbk:=sapply(1:.N,function(i){
    z       <-  compdate[i]-compdate[i:1]
    older   <-  which(z>30)
    if (length(older)) min(older)-1L else as(NA,'integer')
}),by=judge]
# compute cumsum(today) - cumsum(more than 30 days ago)
ldt[,wload:=list(sapply(1:.N,function(i)
    nrun[i]-ifelse(is.na(lookbk[i]),0,nrun[i-lookbk[i]])
))]

在我的笔记本电脑上,这需要一分钟。运行此命令以查看一个判断的输出:

print(ldt['XYZ'],nrow=120)