Для полноты картины есть также функция accumulate()
из пакета purrr
.
Итак, основываясь на ответах Сотос и ThomasIsCoding :
df <- data.frame(a = 1:10)
df$b <- purrr::accumulate(df$a, paste, sep = "-")
df
a b
1 1 1
2 2 1-2
3 3 1-2-3
4 4 1-2-3-4
5 5 1-2-3-4-5
6 6 1-2-3-4-5-6
7 7 1-2-3-4-5-6-7
8 8 1-2-3-4-5-6-7-8
9 9 1-2-3-4-5-6-7-8-9
10 10 1-2-3-4-5-6-7-8-9-10
Разница с Reduce()
в том, что
- в том, что
accumulate()
сам по себе является глаголом функции (нет требуется дополнительный параметр accumulate = TRUE
) - и дополнительные аргументы, такие как
sep = "-"
, могут быть переданы в сопоставленную функцию, что может помочь избежать создания анонимной функции.
РЕДАКТИРОВАТЬ
Если я правильно понимаю, что OP редактирует вопрос, ОП спрашивает, можно ли заменить for
l oop, итеративно вычисляющий результат, на lapply()
.
This Сложно ответить за меня. Вот некоторые мысли и наблюдения:
Первый , accumulate()
все еще будет работать:
set.seed(1L) # required for reproducible data
df <- data.frame(a = sample(0:1, 10L, TRUE))
df$b <- purrr::accumulate(df$a, paste, sep = "-")
df
a b
1 0 0
2 1 0-1
3 0 0-1-0
4 0 0-1-0-0
5 1 0-1-0-0-1
6 0 0-1-0-0-1-0
7 0 0-1-0-0-1-0-0
8 0 0-1-0-0-1-0-0-0
9 1 0-1-0-0-1-0-0-0-1
10 1 0-1-0-0-1-0-0-0-1-1
Это возможно, потому что вычисление a
можно извлечь из l oop, так как оно не зависит от b
.
ИМХО, accumulate()
и Reduce()
делают то, что ищет OP, но не называется lapply()
: они берут результат предыдущей итерации и объединяют его с фактическим значением, например
Reduce(`+`, 1:3)
возвращает сумму 1, 2 и 3 путем итеративного вычисления (((0 + 1) + 2) + 3)
. Это можно визуализировать с помощью параметра accumulate
Reduce(`+`, 1:3, accumulate = TRUE)
[1] 1 3 6
Секунда , между for
l * 1134 существует существенная разница * и функции семейства lapply()
: lapply(X, FUN, ...)
требует вызова функции FUN
для каждого элемента X
. Таким образом, применяются общие правила для функций.
Когда мы пересаживаем тело l oop в анонимную функцию в lapply()
a <- c()
b <- c()
set.seed(1L) # required for reproducible data
lapply(1:10, function(i) {
a <- c(a, sample(c(0,1), 1))
b <- c(b, (paste(a, collapse = "-")))
})
, мы получаем
[[1]]
[1] "0"
[[2]]
[1] "1"
[[3]]
[1] "0"
[[4]]
[1] "0"
[[5]]
[1] "1"
[[6]]
[1] "0"
[[7]]
[1] "0"
[[8]]
[1] "0"
[[9]]
[1] "1"
[[10]]
[1] "1"
data.frame(a, b)
data frame with 0 columns and 0 rows data.frame(a, b)
Из-за правил области действия a
и b
внутри функция считается локальной для функции. Не делается никаких ссылок на a
и b
, определенные вне функции.
Это можно исправить с помощью глобального назначения с использованием глобального назначения оператор <<-
:
a <- c()
b <- c()
set.seed(1L) # required for reproducible data
lapply(1:10, function(i) {
a <<- c(a, sample(c(0,1), 1))
b <<- c(b, (paste(a, collapse = "-")))
})
data.frame(a, b)
a b
1 0 0
2 1 0-1
3 0 0-1-0
4 0 0-1-0-0
5 1 0-1-0-0-1
6 0 0-1-0-0-1-0
7 0 0-1-0-0-1-0-0
8 0 0-1-0-0-1-0-0-0
9 1 0-1-0-0-1-0-0-0-1
10 1 0-1-0-0-1-0-0-0-1-1
Однако global assignment
считается плохой практикой программирования и его следует избегать, см., например, 6th Круг Патрик Бернс 'The R Inferno и множество вопросов по SO.
Третий , способ написания l oop увеличивает векторы в л * * 1 137. Это также считается плохой практикой, поскольку требует многократного копирования данных, что может значительно замедлиться с увеличением размера. См., Например, 2-й круг Патрика Бернса 'The R Inferno .
Однако исходный код
a <- c()
b <- c()
set.seed(1L) # required for reproducible data
for (i in 1:10) {
a <- c(a, sample(c(0,1), 1))
b <- c(b, (paste(a, collapse = "-")))
}
data.frame(a, b)
можно восстановить - записывается как
a <- integer(10)
b <- character(10)
set.seed(1L) # required for reproducible data
for (i in seq_along(a)) {
a[i] <- sample(c(0,1), 1)
b[i] <- if (i == 1L) a[1] else paste(b[i-1], a[i], sep = "-")
}
data.frame(a, b)
Здесь векторы предварительно выделяются с требуемым размером для хранения результата. Элементы для обновления идентифицируются по подписке.
Расчет b[i]
по-прежнему зависит только от значения предыдущей итерации b[i-1]
и фактического значения a[i]
в соответствии с запросом OP.