Я пытаюсь ускорить вычисление с использованием матрицы расстояния. Следующий фрагмент кода работает в скрипте, из которого он пришел, но работает медленно. Он выбирает конкретную комбинацию страны, года и сценария, вычисляет 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
Не могли бы вы привести некоторые примерные данные, чтобы проблема стала воспроизводимой. – hannes101
Вы уверены, что код не содержит ошибок? похоже, нет «IMPACT_code», а скорее «питательного вещества»? –
в любом случае это то, что вы ищете? '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», «год», «питательное вещество»)) ' –