【发布时间】:2018-05-01 05:40:13
【问题描述】:
我知道,如果 R 没有在 for 循环的范围内更新变量,那么我只是编写了一些极其缓慢和昂贵的代码。不幸的是,由于有一系列非常紧迫的截止日期和强大的 C++/Java 背景,在我戴上 R 帽子之前,这是我的首选行为。
我有一个需要改进的功能。它需要一个数据框(如下所示)返回唯一的 patid 值,并使用这些值来检索该数据框的子集以进行日期修改。下面是一个经过修剪的示例(注意,我刚刚将其从已完成的运行中拉出,因此日期已被修改)。我执行的最后一次 R 运行是超过 2700 万行的数据帧,大约需要四/五个小时。数据框的大小会大很多。
patid eventdate
1 12/03/1998
1 12/03/1998
2 04/03/2007
3 15/11/1980
3 15/11/1980
3 01/02/1981
函数的修剪示例:
rearrangeDates <- function(dataFrame) {
#return a list of the unique patient ids
uniquePatids <- getUniquePatidList(dataFrame) #this is only called once and is very fast
out=NULL
for(i in 1:length(uniquePatids)) { # iterate over the list
idf <- subset(dataFrame, dataFrame$patid=uniquePatids[[i]])
idf$eventdate <- as.POSIXct(idf$eventdate,format="%d/%m/%Y")
idf <- idf[order(idf$eventdate,decreasing=FALSE),]
out = rbind(out,idf)
}
return(out)
}
谁能提出改进建议?
【问题讨论】:
-
您是否只是想将日期转换为
POSIX.ct,然后按 patid 和升序排列? -
试试
library(dplyr); df %>% mutate(eventdate = as.Date(eventdate, format="%d/%m/%Y")) %>% arrange(patid, eventdate) -
@Prem 哇!这需要花费数小时并将其减少到几秒钟的东西!谢谢。
-
您是否在每次循环迭代中继续将输入日期作为字符串读取,并将它们转换为
as.Date()?!只需在循环外执行一次dataFrame$eventdate <- as.POSIXct(dataFrame$eventdate,format="%d/%m/%Y")。 -
而迭代追加
out = rbind(out,idf)是一个臭名昭著的反模式。您已经知道输出 df 的长度为length(uniquePatids),您可以在循环外预先声明它。在循环内部,不做追加,直接赋值给 outputDf 的行。
标签: r for-loop optimization dplyr data.table