У меня есть такие данные:
library(dplyr)
set.seed(123)
data <- data.frame(
date = rep(1:3, each=3),
grupo = rep(c("A", "B", "C"), 3),
x = runif (9, 10, 50),
y = runif (9, 20, 100),
z = runif (9, 5, 30)
)
# Convert group into factor
data$grupo <- as.factor(data$grupo)
# Order data
data <- data %>% arrange(grupo, date)
Я хочу, чтобы первое наблюдение каждой строки было (1+original_value/100). Однако, начиная со второй строки, я хочу, чтобы формула была изменена на первое_модифицированное_значение*(1 + второе_наблюдаемое_значение/100), подойдет третья новая строка: второе_модифицированное_значение*(1 + третье_наблюдаемое_значение/100).
Я создал следующую формулу, но не могу утверждать, что lag() должен принимать измененное значение, а не задержку (исходное значение):
# Apply formula in each group for variables, x,y,z
dataaa <- data %>%
group_by(grupo) %>%
mutate(across(c(x, y, z), ~if_else(row_number() == 1, (1 + ./100), lag(.)*(1 + ./100))))
Любая помощь?
Здесь ответом будет функция cumprod()
, поскольку вы умножаете каждое значение на предыдущий результат:
dataaa <- data %>%
group_by(grupo) %>%
mutate(across(c(x, y, z), ~cumprod(1 + . / 100)))
dataaa
# A tibble: 9 × 5
# Groups: grupo [3]
date grupo x y z
<int> <fct> <dbl> <dbl> <dbl>
1 1 A 1.22 1.57 1.13
2 2 A 1.77 2.73 1.38
3 3 A 2.32 5.24 1.68
4 1 B 1.42 1.97 1.29
5 2 B 2.09 3.26 1.56
6 3 B 3.04 4.55 1.91
7 1 C 1.26 1.56 1.27
8 2 C 1.41 2.00 1.65
9 3 C 1.87 2.47 1.96
Вы можете использовать Reduce()
здесь. Я делаю небольшую функцию f()
, которая принимает вектор (x
) и устанавливает init
равным 1 + x[1[/100). right
и accumulate
установлены на F
и T
соответственно.
f <- \(x) Reduce(\(p,i) p*(1+x[i]/100),x=2:length(x), init=1+x[1]/100,F,T)
mutate(data, across(c(x,y,z),f),.by = grupo)
Выход:
date grupo x y z
1 1 A 1.215031 1.565292 1.131980
2 2 A 1.765692 2.726827 1.384639
3 3 A 2.315249 5.235126 1.680850
4 1 B 1.415322 1.965467 1.288626
5 2 B 2.089280 3.258954 1.559401
6 3 B 3.044013 4.552335 1.913591
7 1 C 1.263591 1.562667 1.272385
8 2 C 1.412976 2.003870 1.652278
9 3 C 1.865939 2.472070 1.959628
это лучше, чем мой ответ; подход
Reduce
действительно повышает ценность только в том случае, если ваша реальная проблема сложнее, чем простой совокупный продукт.