2014-01-22 3 views
2

Я довольно много искал, как упростить код для проблемы ниже, но не был успешным. Я полагаю, что с каким-то apply -magic можно ускорить процесс немного, но до сих пор я до сих пор мои трудности с таким родом функции ....R, избавляющийся от вложенных циклов

У меня есть data.frame data, структурированные следующим образом :

year iso3c gdpppc elec solid liquid heat 
2010 USA 1567 1063 1118 835 616 
2015 USA 1571  NA NA NA  NA 
2020 USA 1579  NA NA NA  NA 
... USA  ...  NA NA NA  NA 
2100 USA 3568  NA NA NA  NA 
2010 ARG  256 145 91 85  37 
2015 ARG  261  NA NA NA  NA 
2020 ARG  270  NA NA NA  NA 
... ARG  ...  NA NA NA  NA 
2100 ARG  632  NA NA NA  NA 

Как вы можете видеть, у меня есть историческое начальное значение на 2010 год и полный сценарий gdppc до 2100. Я хочу, чтобы значения elec, solid, liquid и heat растут в соответствии с некоторой эластичностью с в отношении развития gdppc, но отдельно для каждой страны (закодировано в iso3c). У меня есть эластичность, определенная в отдельном data.frame parameters:

item value 
    elec 0.5 
liquid 0.2 
solid -0.1 
    heat 0.1 

До сих пор я использую вложенную for цикла:

for (e in 1:length(levels(parameters$item)){ 
    for (c in 1:length(levels(data$iso3c)){ 
    tmp <- subset(data, select=c("year", "iso3c", "gdppc", parameters[e, "item"]), subset=("iso3c" == levels(data$iso3c)[c])) 

    tmp[tmp$year %in% seq(2015, 2100, 5), parameters[e, "item"]] <- 
     tmp[tmp$year == 2010, parameters[e, "item"]] * 
     cumprod((1 + (tmp[tmp$year %in% seq(2015, 2100, 5), "gdppc"]/
     tmp[tmp$year %in% seq(2010, 2095, 5), "gdppc"] - 1) * parameters[e, "value"])) 

    data[data$iso3c == levels(data$iso3c)[i] & data$year %in% seq(2015, 2100, 5), parameters[e, "item"]] <- tmp[tmp$year > 2010, parameters[e, "item"]] 

    } 
} 

Внешний цикл перебирает колонны и внутренняя один над страны. Внутренний цикл работает для каждой страны (у меня есть 180 стран). Во-первых, выбирается подмножество, содержащее данные по одной отдельной стране и переменной интереса. Затем я позволю соответствующей переменной расти с определенной эластичностью к росту в gdppc и, наконец, вернул подмножество на место в data. Я уже пытался позволить параллельному запуску внешнего цикла, используя foreach, но не удалось выполнить рекомбинацию результатов. Поскольку я должен часто выполнять подобные вычисления, я был бы очень благодарен за любую помощь.

Thanks

ответ

3

Это один из способов. Обратите внимание, я переименовал свой parameters data.frame в p

library(data.table) 
library(reshape2) 

dt <- data.table(data) 
dt.melt = melt(dt,id=1:3) 
dt.melt[,value:=as.numeric(value)] # coerce value column to numeric 
dt.melt[,value:=head(value,1)+(gdpppc-head(gdpppc,1))*p[p$item==variable,]$value, 
     by="iso3c,variable"] 
result <- dcast(dt.melt,iso3c+year+gdpppc~variable) 
result 
# iso3c year gdpppc elec solid liquid heat 
# 1 ARG 2010 256 145.0 91.0 85.0 37.0 
# 2 ARG 2015 261 147.5 90.5 86.0 37.5 
# 3 ARG 2020 270 152.0 89.6 87.8 38.4 
# 4 ARG 2100 632 333.0 53.4 160.2 74.6 
# 5 USA 2010 1567 1063.0 1118.0 835.0 616.0 
# 6 USA 2015 1571 1065.0 1117.6 835.8 616.4 
# 7 USA 2020 1579 1069.0 1116.8 837.4 617.2 
# 8 USA 2100 3568 2063.5 917.9 1235.2 816.1 

Основная идея заключается в том, чтобы использовать функцию melt(...), чтобы изменить исходный data в «длинный» формат, в котором значения в четырех столбцах твердых, жидких, элек, и тепло находятся в одной колонке, value, а в колонке variable указано, к какой метрике относится value. Теперь, используя таблицы данных, вы можете легко заполнить значения. Затем переформатируйте результат обратно в широкий формат, используя dcast(...).

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