Использование sapply для столбца с пропущенными значениями - PullRequest
0 голосов
/ 05 марта 2019

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

Скажем, у меня есть временной ряд индексов, которые начинаются с сегодняшнего дня и заканчиваются через несколько лет,Мои оригинальные индексы существуют только в течение первых нескольких лет.Затем я хочу искусственно расширить эти индексы, используя предполагаемое изменение% (скажем, 10%) для оставшихся лет, и сохранить его как новый столбец.

Вот мой примерный набор данных:

data <- data.frame(
date = seq.Date(as.Date("2019-01-01"),as.Date("2021-01-01"),"3 months"),
index = c(1,1.2,1.4,1.5,1.6,1.7,NA,NA,NA)
)

Теперь я могу создать новый столбец index2, используя цикл for:

data$index2 <- 1
for (i in 1:nrow(data)) {
  if (!is.na(data$index[i])) {
    data$index2[i] = data$index[i]
  }
  else {
  data$index2[i] = data$index2[i-1]*1.1
  }
}

Однако я не могу понять, как мне этого добиться, используя функции apply.Еще раз спасибо за любой совет.

1 Ответ

0 голосов
/ 05 марта 2019

Если я правильно понял, это похоже на работу для lag:

library(dplyr)
data %>% mutate(index2 = if_else(!is.na(index), index, lag(index) * 1.1))
#        date index index2
#1 2019-01-01   1.0   1.00
#2 2019-04-01   1.2   1.20
#3 2019-07-01   1.4   1.40
#4 2019-10-01   1.5   1.50
#5 2020-01-01   1.6   1.60
#6 2020-04-01   1.7   1.70
#7 2020-07-01    NA   1.87
#8 2020-10-01    NA     NA
#9 2021-01-01    NA     NA

Это воспроизводит ваш ожидаемый результат (то есть заменяет только первый NA);Возможно, я неправильно понял вашу формулировку проблемы, но я не понимаю, что *apply могло бы быть связано с этим.


Вы могли бы реализовать sapply местоположение, подобное этому

transform(data, index2 = c(index[1], sapply(seq_along(index)[-1], function(i)
    if (!is.na(index[i])) index[i] else index[i - 1] * 1.1)))
#        date index index2
#1 2019-01-01   1.0   1.00
#2 2019-04-01   1.2   1.20
#3 2019-07-01   1.4   1.40
#4 2019-10-01   1.5   1.50
#5 2020-01-01   1.6   1.60
#6 2020-04-01   1.7   1.70
#7 2020-07-01    NA   1.87
#8 2020-10-01    NA     NA
#9 2021-01-01    NA     NA

но это не очень красиво.


После исправления опечатки формулировка проблемы немного меняется, и нам нужно cumprod

data %>%
    mutate(index2 = if_else(
        !is.na(index),
        index,
        index[which.max(index)] * cumprod(c(rep(1.0, sum(!is.na(index))), rep(1.1, sum(is.na(index)))))))
#        date index index2
#1 2019-01-01   1.0 1.0000
#2 2019-04-01   1.2 1.2000
#3 2019-07-01   1.4 1.4000
#4 2019-10-01   1.5 1.5000
#5 2020-01-01   1.6 1.6000
#6 2020-04-01   1.7 1.7000
#7 2020-07-01    NA 1.8700
#8 2020-10-01    NA 2.0570
#9 2021-01-01    NA 2.2627
...