在R中调整for循环的速度

时间:2015-02-10 23:08:40

标签: r performance for-loop automation vectorization

我已经阅读了矢量化作为加速for循环的解决方案。但是,我在for循环中创建的数据结构似乎需要是data.frame / table。

以下是该方案:

我有一个大型的序列号和时间戳表。多个时间戳可以应用于相同的序列号。我只想要每个序列号的最新时间戳。

我现在的方法是创建一个具有唯一序列号的向量。然后,对于通过此向量的每个循环,我创建一个临时表,其中包含序列号/时间戳组合的所有观察结果(' temp')。然后我接受这个临时表的最后一个条目(使用tail命令)并将其放入另一个表中,该表最终将保存所有唯一的序列号及其最新的时间戳(' last.pass')。最后,我只是从起始表序列中删除无法找到数字/时间戳组合的行' last.pass'

这是我的代码:

#create list of unique serial numbers found in merged 9000 table
hddsn.unique <- unique(merge.data$HDDSN)

#create empty data.table to populate
last.pass < data.table(HDDSN=as.character(1:length(hddsn.unique)),
   ENDDATE=as.character(1:length(hddsn.unique)))

#populate last.pass with the combination of serial numbers and their latest timestamps
for (i in 1:length(hddsn.unique)) {
  #create temporary table that finds all serial number/timestamp combinations
  temp <- merge.data[merge.data$HDDSN %in% hddsn.unique[i],][,.(HDDSN, ENDDATE)]
  #populate last.pass with the latest timestamp record for every serial number
  last.pass[i,] <- tail(temp, n=1)
}

match <- which(merge.data[,(merge.data$HDDSN %in% last.pass$HDDSN) &
         (merge.data$ENDDATE %in% last.pass$ENDDATE)]==TRUE)
final <- merge.data[match]

我的最终问题是,如何通过矢量化或将其转换为函数来加快速度,从而保持此脚本的自动化特性。

谢谢!!!

2 个答案:

答案 0 :(得分:0)

这个怎么样?如果不清楚输入数据是什么样的,我就会猜测。

# make some dummy data with multiple visits per serial
merge.data <- data.frame(HDDSN = 1001:1020, 
    timestamps = sample(1:9999, 100))

# create a function to find the final visit for a given serial
fun <- function(serial) {
    this.serial <- subset(merge.data, HDDSN==serial)
    this.serial[which.max(this.serial$timestamps), ]
}

# apply the function to each serial number and clean up the result
final <- as.data.frame(t(sapply(unique(merge.data$HDDSN), fun)))

答案 1 :(得分:0)

此数据对每个HDDSN都有几个ENDDATE

merge.data <- data.frame(HDDSN = 1001:1100, ENDDATE = sample(9999, 1000))

按顺序排列,首先是HDDSN,然后是ENDDATE

df = merge.data[do.call("order", merge.data),]

然后找到每个HDDSN的最后一个条目

df[!duplicated(df[["HDDSN"]], fromLast=TRUE),]

以下说明了关键步骤

> head(df, 12)
    HDDSN    ENDDATE
701  1001          4
101  1001        101
1    1001       1225
301  1001       2800
201  1001       6051
501  1001       6714
801  1001       6956
601  1001       7894
401  1001       8234
901  1001       8676
802  1002        247
402  1002        274
> head(df[!duplicated(df[["HDDSN"]], fromLast=TRUE),])
    HDDSN    ENDDATE
901  1001       8676
902  1002       6329
803  1003       9947
204  1004       8825
505  1005       8472
606  1006       9743

如果有复合键,则在data.frame而不是向量!duplicated(df[, c("key1", "key2")])上查找重复项,如下所示:

> df = data.frame(k0=c(1:3, 1:6), k1=1:3)
> df[!duplicated(df, fromLast=TRUE),]
  k0 k1
1  1  1
2  2  2
3  3  3
7  4  1
8  5  2
9  6  3

(行号来自原始数据帧,因此第4-6行是重复的)。 (可能需要注意,特别是如果其中一列是数字的,因为duplicated.data.frame将列粘贴到一个字符串中并且舍入错误可能会蔓延)。