#r
#r
Вопрос:
Пытаюсь изучить лучшие решения, чем for-циклы, и чувствую, что этот экземпляр может подойти для lapply или mapply.
У меня есть фрейм данных из двух столбцов (объемы, месяцы.пройдено) из разных моментов времени, я уменьшаю по вектору значений снижения (declease.vector), при котором точка начала снижения изменяется в зависимости от пройденного месяца 1 месяц, до конца declease.vector.
В настоящее время мое решение, которое работает нормально, является:
decline.vector <- c( 0.9,0.81,0.729,0.656,0.590,0.531,0.478, 0.430, 0.387,0.348)
months.passed <- c(2,4,5,6)
volumes <- c(10,20,10,20)
df <- data.frame(months.passed, volumes)
for(i in 1:nrow(df)) {
build <- df$volumes[i] * cumprod(decline.vector[df$months.passed[i] 1:nrow(decline.vector),])
build <- rbind(final,build)
}
return(build)
[1] NA NA 7.29 6.56 5.90 5.31 4.78 4.30 3.87 3.49
[2] NA NA NA NA 11.81 10.63 9.57 8.61 7.75 6.97
[3] NA NA NA NA NA 5.31 4.78 4.30 3.87 3.49
[4] NA NA NA NA NA NA 9.57 8.61 7.75 6.97
Есть ли более элегантный способ сделать это, либо используя lapply
or mapply
, либо даже что-то вместо rbind?
Комментарии:
1. Цикл for у меня не работает, поскольку ваш код, похоже, предполагает, что
decline.vector
это матрица или фрейм данных, а не вектор, который вы предоставляете, среди прочих проблем. Я могу исправить их и получить результат, аналогичный тому, который вы предоставляете, но без реального воспроизводимого примера невозможно узнать формат, который вы ожидаете, что было бы необходимо для предоставления вам более полезной информации.2. Тай дивибисан, не осознавал, что я на самом деле выбираю decline.vector из фрейма данных, используя dplyr в моем реальном коде, не думал, что это будет иметь значение здесь для примера, но вижу, что это имеет значение.
Ответ №1:
Вот вариант, использующий mapply
out1 <- t(mapply(
function(x, y, z = decline.vector) {
n <- length(z)
c(rep(NA, y), x * z[(y 1):n])
},
x = volumes,
y = months.passed
))
out1
# [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
#[1,] NA NA 7.29 6.56 5.9 5.31 4.78 4.3 3.87 3.48
#[2,] NA NA NA NA 11.8 10.62 9.56 8.6 7.74 6.96
#[3,] NA NA NA NA NA 5.31 4.78 4.3 3.87 3.48
#[4,] NA NA NA NA NA NA 9.56 8.6 7.74 6.96
Векторизованный вариант, в котором мы используем матричное умножение
out2 <- t(t(volumes)) %*% t(decline.vector)
Затем мы используем матрицу для вставки NA
s в первые months.passed
столбцы для каждой строки
out2[cbind(rep(1:length(months.passed), months.passed),
sequence(months.passed))] <- NA
Результат
identical(out1, out2)
# [1] TRUE
данные
decline.vector <- c(0.9, 0.81, 0.729, 0.656, 0.590, 0.531, 0.478, 0.430, 0.387, 0.348)
volumes <- c(10, 20, 10, 20)
months.passed <- c(2, 4, 5, 6)
Комментарии:
1. Это потрясающе, спасибо тебе за это, Маркус, несмотря на недостаток моего воспроизводимого примера.