R избавляется от вложенных для петель
Я довольно много искал, как упростить код для решения проблемы ниже, но не увенчался успехом. Я предполагаю, что с каким-то apply
-магические можно немного ускорить, но до сих пор у меня все еще есть трудности с такими функциями....
У меня есть 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
но не было успешной рекомбинации результатов. Поскольку мне приходится часто проводить подобные вычисления, я был бы очень благодарен за любую помощь.
Спасибо
1 ответ
Вот один из способов. Обратите внимание, я переименовал ваш parameters
data.frame to 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
в "длинный" формат, где значения в четырех столбцах solid, liquid, elec и heat находятся в одном столбце, value
и столбец variable
указывает, какой показатель value
относится к. Теперь, используя таблицы данных, вы можете легко заполнить значения. Затем измените результат обратно в широкоформатный формат, используя dcast(...)
,