последовательное вычитание из векторных элементов

Мне нужно вычесть число из вектора таким образом, чтобы оно последовательно вычиталось из элементов. В качестве примера рассмотрим вектор a = c(8, 4). Если я хочу последовательно вычесть 9 из этого вектора, я сначала вычитаю 9 из первого элемента вектора, 8. Это оставляет 0 для первого элемента с напоминанием 1, которое затем вычитается из второго элемента. Это оставляет 4-1 = 3 для второго элемента вектора.

Я могу сделать это с помощью набора неэлегантных операторов if-else. Должен быть способ получше. Проще было бы показать примеры:

Я предполагаю, что функция последовательного вычитания называется serialSub.

a = c(8,4)
serialSub(a,4)
> [1] 4 4

serialSub(a,8)
> [1] 0 4

serialSub(a,9)
> [1] 0 3

serialSub(a,13)
> [1] 0 0

serialSub(a,0)
> [1] 8 4

r
person Eric    schedule 15.09.2017    source источник


Ответы (1)


Если tosub - это общая сумма, которую нужно вычесть, то pmin(cumsum(a), tosub) - это общая сумма, которая должна быть удалена из каждого элемента кумулятивной суммы a, и, следовательно, cumsum(a) - pmin(cumsum(a), tosub) является кумулятивной суммой нашего нового вектора. Нам нужно получить вектор, который дает эту кумулятивную сумму, что можно сделать с помощью diff:

a <- c(8, 4)
serialSub <- function(a, tosub) diff(c(0, cumsum(a) - pmin(cumsum(a), tosub)))
serialSub(a,4)
# [1] 4 4
serialSub(a,8)
# [1] 0 4
serialSub(a,9)
# [1] 0 3
serialSub(a,13)
# [1] 0 0
serialSub(a,0)
# [1] 8 4
person josliber♦    schedule 15.09.2017
comment
Или pmin(pmax(0, cumsum(a) - v), a), я думаю. - person Frank; 15.09.2017
comment
@Frank, хороший вариант - pmax(0, cumsum(a) - v) также работает для желаемой совокупной суммы результирующего вектора, и мне нравится наблюдение, что мы можем просто использовать pmin между этим и a, чтобы определить, что оставить, вместо использования diff. - person josliber♦; 15.09.2017