【问题标题】:For loop takes forever to runFor循环需要永远运行
【发布时间】:2014-11-23 18:52:27
【问题描述】:

我有两张桌子。一个有 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分钟采样:

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

现在,我需要第二个表的第 2 行和第 3 行的值与第一个表相关联,这样如果第二个表的时间戳介于第一个表的 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

【问题讨论】:

  • 您将cloudfull 中的每一行与cloud 中的每一行进行比较。如果两者都有 470000 个条目,则比较 470000*470000,这很多。假设两个输入文件都按日期时间顺序排序,然后对“合并”两个文件进行一些研究。
  • AdrianHHH 是对的,它不是 R 特定的,它是关于通用算法的。使用某种索引来减少搜索时间。不要使用 for 循环,您使用的是复杂度为 o(n^2) 的算法。一个排序表应该把它带到 o(n log(n)),如果你能负担得起,只需制作一个直数组(因为你的数据是等距的,没有空洞)使它成为 o(n)
  • cloud 按 3 小时采样,而 cloudFull 按 1 分钟采样,这意味着云要小 180 倍。但我会考虑“合并”,谢谢!
  • 使用包 data.table 并进行滚动连接。 (此外,您正在为循环内的单个值调用 strptime。您可以使用循环外的整个向量来执行此操作。事实上,如果您使用向量化,则不需要内部循环。)
  • 在for循环外提升向量化操作,例如循环外dateOne &lt;- strptime(cloudFull[,1], '%d.%m.%Y %H:%M'),内dateOne[i];对于其他 strptime() 调用也是如此。 findInterval() 是一种将细粒度数据放入(排序)箱的有效方法;与时俱进可能需要一些技巧。

标签: r performance for-loop rstudio


【解决方案1】:

很难知道您的真实数据是什么样的,但大致如下

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() 将问题变为线性扩展而不是二次扩展的问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-01-23
    • 1970-01-01
    • 1970-01-01
    • 2021-12-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多