循环需要运行很长时间

3

我有两张表格。其中一张包含从2012年到2014年的信息,时间间隔为3小时。它看起来像这样:

                    B   C
1   01.06.2012 00:00    10  0   
2   01.06.2012 03:00    10  0   
3   01.06.2012 06:00    10  6   
4   01.06.2012 09:00    7,5 0   
5   01.06.2012 12:00    6   2,5 
6   01.06.2012 15:00    6   0   
7   01.06.2012 18:00    4   0   
8   01.06.2012 21:00    4   0   
9   02.06.2012 00:00    0   0   
10  02.06.2012 03:00    0   0 

另一个表格是同一时间点抽样,但每分钟进行一次:

1   01.06.2012 00:00       
2   01.06.2012 00:01       
3   01.06.2012 00:01       
4   01.06.2012 00:03       
5   01.06.2012 00:03       
6   01.06.2012 00:05       
7   01.06.2012 00:05       
8   01.06.2012 00:07       
9   01.06.2012 00:08       
10  01.06.2012 00:09       
11  01.06.2012 00:10

现在,我需要第二个表格的第二行和第三行的值与第一个表格相关联,以便如果第二个表格的时间戳在第一个表格的timestamp(i)timestamp(i+1)之间,则会获取B(i)C(i)并将它们复制。我有这段代码,并且我知道它能工作,但运行它需要超过12小时,而我有许多这样的文件需要按照相同的方式处理。
clouds <- read.csv('~/2012-2014 clouds info.csv', sep=";", header = FALSE)
cloudFull <- read.csv('~/2012-2014 clouds.csv', sep=";", header = FALSE)

for (i in 1:nrow(cloudFull)){
  dateOne <- strptime(cloudFull[i,1], '%d.%m.%Y %H:%M')

  for (j in 1:nrow(clouds)){
    bottomDate = strptime(clouds[j,1], '%d.%m.%Y %H:%M')
    upperDate = strptime(clouds[j+1,1], '%d.%m.%Y %H:%M')
    if  ((dateOne >= bottomDate) && (dateOne < upperDate)) {
      cloudFull[i,2] <- clouds[j,2]
      cloudFull[i,3] <- clouds[j,3]
      break

    } 

  }
}

write.csv(cloudFull, file = 'cc.csv')

现在我该如何使它运行更快呢?object.size(cloudFull)告诉我它占用了39580744字节,其中有470000行数据,而其他文件可能有更多的数据。我刚开始学习R语言(迄今为止只学了2天),如果能用非常简单易懂的语言给些建议,我将不胜感激:D。


1
你正在将cloudfull中的每一行与cloud中的每一行进行比较。如果它们都有470000条目,则需要进行470000*470000次比较,这非常多。假设两个输入文件按日期时间顺序排序,那么请研究一下如何"合并"两个文件。 - AdrianHHH
AdrianHHH是正确的,这不是R特定的,而是关于一般算法的。使用某种索引来减少搜索时间。不要使用for循环,因为你正在使用一个复杂度为o(n^2)的算法。一个排序的表应该将其降至o(n log(n)),如果你能负担得起,只需制作一个直接数组(因为你的数据是等距离的且没有空洞),使其变成o(n)。 - BlueTrin
云是每3小时采样一次,而cloudFull是每1分钟采样一次,这意味着云比cloudFull小180倍。但我会研究“合并”的,谢谢! - Dana Sharipova
使用数据包data.table并进行滚动连接。 (此外,您正在在循环内为单个值调用strptime。您可以在循环外使用整个向量来完成此操作。实际上,如果使用矢量化,则不需要内部循环。) - Roland
将可向量化的操作提取到for循环之外,例如将dateOne <- strptime(cloudFull[,1], '%d.%m.%Y %H:%M')放在循环之外,而将dateOne[i]放在循环内;对于其他的strptime()调用也是如此。findInterval()是一种有效的方法,可以将细粒度数据放入(排序)箱中;这可能需要一些技巧来处理时间。 - Martin Morgan
1个回答

4

很难得知你的真实数据长什么样,但是大致如下

full <- strptime(cloudFull[,1], '%d.%m.%Y %H:%M')
ref <- strptime(clouds[,1], '%d.%m.%Y %H:%M')
## ref <- sort(ref)
cloudsFull[, 2:3] <- clouds[findInterval(full, ref), 2:3]

使用findInterval()可以将问题转化为线性缩放而不是二次缩放。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接