Для цикла требуется вечность для запуска

У меня есть две таблицы. Есть информация с 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


person Dana Sharipova    schedule 29.09.2014    source источник
comment
Вы сравниваете каждую строку в cloudfull с каждой строкой в ​​cloud. Если у обоих есть 470000 записей, то это 470000 * 470000 сравнивается, что много. Предполагая, что оба входных файла отсортированы по дате и времени, проведите некоторое исследование по объединению двух файлов.   -  person AdrianHHH    schedule 29.09.2014
comment
AdrianHHH прав, это не специфично для R, это общие алгоритмы. Используйте какой-нибудь индекс, чтобы сократить время поиска. Не используйте цикл for, вы используете алгоритм порядка o(n^2) с точки зрения сложности. Отсортированная таблица должна привести к o (n log (n)) и, если вы можете себе это позволить, просто создайте прямой массив (поскольку ваши данные равномерно распределены без отверстий), чтобы сделать его o (n)   -  person BlueTrin    schedule 29.09.2014
comment
Облако отбирается за 3 часа, тогда как cloudFull за 1 минуту, что означает, что облако в 180 раз меньше. но я посмотрю на слияние, спасибо!   -  person Dana Sharipova    schedule 29.09.2014
comment
Используйте пакет data.table и выполните скользящее соединение. (Кроме того, вы вызываете strptime для одиночных значений внутри циклов. Вы можете сделать это со всеми векторами вне циклов. Фактически, внутренний цикл не нужен, если вы используете векторизацию.)   -  person Roland    schedule 29.09.2014
comment
поднимать векторизуемые операции вне цикла for, например dateOne <- strptime(cloudFull[,1], '%d.%m.%Y %H:%M') вне цикла, dateOne[i] внутри; аналогично для других вызовов strptime(). findInterval() — это эффективный способ поместить детализированные данные в (отсортированные) ячейки; может потребоваться некоторое изящество, чтобы работать со временем.   -  person Martin Morgan    schedule 29.09.2014


Ответы (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() изменяет задачу на линейную, а не квадратичную.

person Martin Morgan    schedule 29.09.2014