Удалить поддельное отрицательное значение в R - PullRequest
0 голосов
/ 17 декабря 2018

Мне нужно рассчитать общую сумму для каждого пользователя в наборе данных, но проблема в том, что даже если сумма для пользователя равна 0, она продолжает вычитать и генерировать ложные отрицательные значения (не может быть суммы меньше 0, ее ошибка).

Для каждого + или - есть реальные события.Однако, когда количество достигает 0, независимо от того, сколько отрицательных событий появляется, результат не должен опускаться ниже 0, и если у нас есть первые 10 отрицательных событий, таких как переход к -1000, и после этого у нас есть один положительный +200 и после этого одного отрицательного-100, мне нужно, чтобы конечный результат был 100.

Вот пример, итоговая общая сумма для этого пользователя должна быть 200.

userdata <- read.table(text="
 ID  Amount UserID Date     Hour
 1   500    2      3/3/2018 0:00
 2  -200    2      3/4/2018 0:00
 3  -250    2      3/5/2018 0:00
 4  -500    2      3/8/2018 0:00
 5   100    2      3/8/2018 0:00
 6  -50     2      3/8/2018 0:00
 7   250    2      3/8/2018 0:00
 8  -100    2      3/8/2018 0:00
", header=TRUE, stringsAsFactors=FALSE)

Мне нужен способ, чтобы правильно рассчитать, чтосуммы.

Ответы [ 2 ]

0 голосов
/ 26 января 2019

Если я правильно понимаю, общая сумма вычисляется по совокупной сумме, которая никогда не становится отрицательной.

В то время как Рекурсивный фильтр от AkselA вычисляет итоговые значения, повторяя циклэлементы вектора, подход ниже итеративно исправляет накопленную сумму всякий раз, когда она становится отрицательной.Обратите внимание, что важен порядок элементов, например, временные ряды.

nonneg_cumsum <- function(x) {
  n <- length(x)
  y <- cumsum(x)
  repeat {
    i <- head(which(y < 0), 1L)
    if (length(i) < 1) return(y)
    y[i:n] <- y[i:n] - y[i]
  }
}

nonneg_cumsum(userdata$Amount)
[1] 500 300  50   0 100  50 300 200

Для сравнения, вот выходные данные обычной функции cumsum():

cumsum(userdata$Amount)
[1]  500  300   50 -450 -350 -400 -150 -250
0 голосов
/ 20 декабря 2018

Я думаю, что мы можем решить это с помощью рекурсивного фильтра, своего рода условной кумулятивной суммы.

# Isolate the vector we're interested in and prepend a zero
y <- c(0, userdata$Amount)

# run a for loop
for (i in 2:length(y)) {   # For every position in the vector, 
    y[i] <- y[i-1] + y[i]  # add the previous to the present.
    if (y[i] < 0) {        # If the resulting sum is less than zero,
        y[i] <- 0          # replace it with zero
    }
}

# Or equivalent, but maybe a bit more elegant
for (i in 2:length(y)) { 
    y[i] <- max(c(0, y[i-1] + y[i]))
}

y[-1]
# [1] 500 300  50   0 100  50 300 200  

tail(y, 1)
# 200
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...