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(...),

Другие вопросы по тегам