Ограниченная накопленная сумма?
896 просмотра
3 ответа
Как я могу сделать кумулятивную сумму по вектору (например cumsum
), но ограниченную так, чтобы суммирование никогда не опускалось ниже нижней границы или выше верхней границы?
Стандартная функция cumsum привела бы к следующему.
foo <- c(100, -200, 400, 200)
cumsum(foo)
# [1] 100 -100 300 500
Я ищу что-то такое же эффективное, как и базовая cumsum
функция. Я ожидаю, что результат будет выглядеть следующим образом.
cumsum.bounded(foo, lower.bound = 0, upper.bound = 500)
# [1] 100 0 400 500
Спасибо
Автор: Nick Allen Источник Размещён: 13.11.2019 11:33Ответы (3)
12 плюса
Как уже упоминалось в комментариях, Rcpp
это хороший путь.
cumsumBounded.cpp
:
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
NumericVector cumsumBounded(NumericVector x, double low, double high) {
NumericVector res(x.size());
double acc = 0;
for (int i=0; i < x.size(); ++i) {
acc += x[i];
if (acc < low) acc = low;
else if (acc > high) acc = high;
res[i] = acc;
}
return res;
}
Скомпилируйте и используйте новую функцию:
library(Rcpp)
sourceCpp(file="cumsumBounded.cpp")
foo <- c(100, -200, 400, 200)
cumsumBounded(foo, 0, 500)
# [1] 100 0 400 500
Автор: josliber
Размещён: 21.01.2014 05:20
3 плюса
Вот пара чистых версий R Маловероятно, что он будет таким же быстрым, как C / C ++, но один из них может быть достаточно быстрым для ваших нужд и его будет проще поддерживать:
# 1 Reduce
cumsum.bounded <- function(x, lower.bound = 0, upper.bound = 500) {
bsum <- function(x, y) min(upper.bound, max(lower.bound, x+y))
if (length(x) > 1) Reduce(bsum, x, acc = TRUE) else x
}
# 2 for loop
cumsum.bounded2 <- function(x, lower.bound = 0, upper.bound = 500) {
if (length(x) > 1)
for(i in 2:length(x)) x[i] <- min(upper.bound, max(lower.bound, x[i] + x[i-1]))
x
}
Их может потребоваться немного улучшить, если x
длина равна 0 или 1, в зависимости от того, насколько строгие требования.
3 плюса
Я полагаю, это может сработать.
library ("Rcpp")
cumsum.bounded <- cppFunction(
'NumericVector cumsum_bounded (NumericVector x, const double lower, const double upper) {
double acc = 0;
NumericVector result(x.size());
for(int i = 0; i < x.size(); i++) {
acc += x[i];
if (acc < lower) acc = lower;
if (acc > upper) acc = upper;
result[i] = acc;
}
return result;
}')
Автор: Nick Allen
Размещён: 21.01.2014 07:56
Вопросы из категории :
- r Как получить доступ к последнему значению в векторе?
- r Пакеты оптимизации для R
- r Есть ли у R такие операторские операции, как Perl qw ()?
- r Библиотека / инструмент для рисования тройных / треугольных графиков
- r Участки без заголовков / надписей в R
- r Расчет скользящей средней
- r Режим Emacs ESS - вкладка для области комментариев
- r Преобразование данных из многих строк во многие столбцы
- r Проверить, содержит ли вектор данный элемент
- r Поиск всех позиций для нескольких элементов в векторе
- r Разница между скобками [] и двойной скобкой [[]] для доступа к элементам списка или кадра данных
- r Написание функций на R с учетом объема работ
- r Линейная регрессия и группировка по R
- r Как заставить выполнение приостановить, поспать, подождать X секунд в R?
- r Уровни коэффициента отбрасывания в заданном кадре данных
- r Графики рядом с ggplot2
- r Как отсортировать фрейм данных по нескольким столбцам
- r Как объединить (объединить) кадры данных (внутренний, внешний, левый, правый)?
- r Поворотные и интервальные метки на оси ggplot2
- r Как избежать цикла в R: выбор элементов из списка