Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to keep dropping the first value, until the sum of the vector is less than 20?

I am looking for a function which takes a vector and keeps dropping the first value until the sum of the vector is less than 20. Return the remaining values.

I've tried both a for-loop and while-loop and can't find a solution.

vec <- c(3,5,3,4,3,9,1,8,2,5)

short <- function(vec){

 for (i in 1:length(vec)){
    while (!is.na((sum(vec)) < 20)){
      vec <- vec[i+1:length(vec)]
      #vec.remove(i)
  }
}

The expected output should be: 1,8,2,5 which is less than 20.

like image 464
Hanna Dup Avatar asked Jan 16 '19 07:01

Hanna Dup


Video Answer


1 Answers

Looking at the expected output it looks like you want to drop values until sum of remaining values is less than 20.

We can create a function

drop_20 <- function(vec) {
  tail(vec, sum(cumsum(rev(vec)) < 20))
}

drop_20(vec)
#[1] 1 8 2 5

Trying it on another input

drop_20(1:10)
#[1]  9 10

Breaking down the function, first the vec

vec = c(3,5,3,4,3,9,1,8,2,5)

We then reverse it

rev(vec)
#[1] 5 2 8 1 9 3 4 3 5 3

take cumulative sum over it (cumsum)

cumsum(vec)
#[1]  3  8 11 15 18 27 28 36 38 43

Find out number of enteries that are less than 20

cumsum(rev(vec)) < 20
 #[1]  TRUE  TRUE  TRUE  TRUE FALSE FALSE FALSE FALSE FALSE FALSE

sum(cumsum(rev(vec)) < 20)
#[1] 4

and finally subset these last enteries using tail.


A slight modification in the code and it should be able to handle NAs as well

drop_20 <- function(vec) {
   tail(vec, sum(cumsum(replace(rev(vec), is.na(rev(vec)), 0)) < 20))
}

vec = c(3, 2, NA, 4, 5, 1, 2, 3, 4, 9, NA, 1, 2)
drop_20(vec)
#[1]  3  4  9 NA  1  2

The logic being we replace NA with zeroes and then take the cumsum

like image 86
Ronak Shah Avatar answered Oct 05 '22 22:10

Ronak Shah