2016-11-13 13 views
1

Я пытаюсь ускорить вычисление с использованием матрицы расстояния. Следующий фрагмент кода работает в скрипте, из которого он пришел, но работает медленно. Он выбирает конкретную комбинацию страны, года и сценария, вычисляет MFAD и записывает информацию о комбинации, включая результат MFAD, и rbind в MFADHolder.R Использование rdist для генерации результатов в таблице данных

MFADHolder <- data.table(scenario = character(0), region_code.IMPACT159 = character(0), year = character(0), MFAD = numeric(0)) 
for (k in yearList) {   
    for (l in scenList) {   
    for (n in ctylist) {    
     dt <- dt.main[ year == k & scenario == l & region_code.IMPACT159 == n,]   
     itemlist <- unique(dt$IMPACT_code)    
     dt[,c("scenario", "region_code.IMPACT159", "year", "IMPACT_code") := NULL]    
     d <- as.data.table(rdist(dt))   
     data.table::setnames(d, old = names(d), new = itemlist)   
     MFAD <- sum(d)/20   
     newRow <- as.list(c(l,n,k,MFAD))   
     MFADHolder <- rbind(MFADHolder, newRow)   
    }   
    }   
} 

Используя новый инструмент профилирования Rstudio, я обнаружил, что линия

dt <- dt.main[ year == k & scenario == l & region_code.IMPACT159 == n,] 

занимает большую часть времени вычислений, предположительно, из-за все копирование ДТА. Я думал, что смогу сделать все это в таблице данных. Строка кода ниже могла бы в принципе заменить весь код выше, за исключением того, что он не работает.

dt.main[, MFAD := sum(rdist(dt.main[,!(c("scenario", "region_code.IMPACT159", "year", "IMPACT_code"))]))/20, 
by = c("scenario", "year", "region_code.IMPACT159")] 

Идея заключается в том, чтобы запустить rdist на только соответствующие столбцы в dt.main, заменив код дт копию выше, а затем просуммировать все элементы в матрице расстояний, разделить на 20 и записать все результаты в MFAD.

Когда я запускаю его, он никогда не завершается, и R умирает, потому что у моего mac заканчивается системная память и/или его жесткий диск заканчивается из космоса.

Вот полный код, чтобы продемонстрировать проблему

library(data.table) 
library(fields) # needed for rdist function 
dt.main <- readRDS("dt.main.rds") 
dt.main[, MFAD := sum(rdist(dt.main[,!(c("scenario", "region_code.IMPACT159", "year", "nutrient"))]))/len.nutlist, 
     by = c("scenario", "year", "region_code.IMPACT159")] 

А вот ссылка на файл данных RDS для тестирования - код https://github.com/GeraldCNelson/nutmod/commit/c06b51478223bdc3226cccbe9498df0472a57465#diff-21615ea67b6aed07b31f6c21e89a810b

+1

Не могли бы вы привести некоторые примерные данные, чтобы проблема стала воспроизводимой. – hannes101

+1

Вы уверены, что код не содержит ошибок? похоже, нет «IMPACT_code», а скорее «питательного вещества»? –

+1

в любом случае это то, что вы ищете? 'system.time (dt.main [,': = '(MFAD = sum (rdist (.SD))/.N), by = c (« сценарий »,« год »,« region_code.IMPACT159 »). SDcols = cols]) 'mind' .N', поскольку я не знаю, что такое 'len.nutlist' и где' cols <- setdiff (colnames (dt.main), c («сценарий», «region_code.IMPACT159», «год», «питательное вещество»)) ' –

ответ

1

Джона Смита был в основном именно то, что мне было нужно, но не сделал работать как написано.

Версия ниже делает и работает очень быстро!

cols <- setdiff(colnames(dt.main), c("scenario", "region_code.IMPACT159", "year", "nutrient")) 
system.time(dt.main[, `:=` (MFAD = sum(rdist(.SD))/.N), 
      by = c("scenario", "year", "region_code.IMPACT159"), .SDcols = cols]) 
+0

Это потому, что символ '' имеет особое значение в тексте. рад, что это помогло :) –

 Смежные вопросы

  • Нет связанных вопросов^_^