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












7















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.










share|improve this question









New contributor




Hanna Dup is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.

























    7















    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.










    share|improve this question









    New contributor




    Hanna Dup is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
    Check out our Code of Conduct.























      7












      7








      7








      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.










      share|improve this question









      New contributor




      Hanna Dup is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.












      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.







      r loops for-loop vector while-loop






      share|improve this question









      New contributor




      Hanna Dup is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.











      share|improve this question









      New contributor




      Hanna Dup is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.









      share|improve this question




      share|improve this question








      edited 5 hours ago









      Khaynes

      443417




      443417






      New contributor




      Hanna Dup is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.









      asked 6 hours ago









      Hanna DupHanna Dup

      366




      366




      New contributor




      Hanna Dup is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.





      New contributor





      Hanna Dup is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.






      Hanna Dup is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.
























          4 Answers
          4






          active

          oldest

          votes


















          8














          You need to remove the first value each time, so your while loop should be,



          while (sum(x, na.rm = TRUE) >= 20) {
          x <- x[-1]
          }

          #[1] 1 8 2 5





          share|improve this answer





















          • 1





            From the OP's post, might look like their actual data has NA's in it? If so, remember to define sum(x, na.rm = TRUE)

            – Khaynes
            5 hours ago











          • Good eye! Thanks

            – Sotos
            5 hours ago






          • 3





            Can the downvoter explain please? I went with while to point out OP's mistake! Downvote is at the very least biased

            – Sotos
            5 hours ago





















          7














          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






          share|improve this answer


























          • I think this is the fastest solution so far which of course matters only on a larger vector.

            – Phann
            5 hours ago











          • @Phann or one a large number of small vectors :).

            – snoram
            5 hours ago











          • FYI, you should also handle NA's somewhere in there. Good idea btw :)

            – Sotos
            5 hours ago











          • I don't know why but when I tried your code, the output is integer(0)

            – Hanna Dup
            5 hours ago











          • @HannaDup must be because of NAs you may take a look at the updated answer now.

            – Ronak Shah
            5 hours ago



















          4














          base solution without loops

          not my most readable code ever, but it's pretty fast (see benchmarking below)



          rev( rev(vec)[cumsum( replace( rev(vec), is.na( rev(vec) ), 0 ) ) < 20] )
          #[1] 1 8 2 5


          note: 'borrowed' the NA-handling from @Ronak's answer



          sample data
          vec = c(3, 2, NA, 4, 5, 1, 2, 3, 4, 9, NA, 1, 2)



          benchmarks



          microbenchmark::microbenchmark(
          Sotos = {
          while (sum(vec, na.rm = TRUE) >= 20) {
          vec <- vec[-1]
          }
          },
          Ronak = tail(vec, sum(cumsum(replace(rev(vec), is.na(rev(vec)), 0)) < 20)),
          Wimpel = rev( rev(vec)[cumsum( replace( rev(vec), is.na( rev(vec) ), 0 ) ) < 20]),
          WimpelMarkus = vec[rev(cumsum(rev(replace(vec, is.na(vec), 0))) < 20)]
          )


          # Unit: microseconds
          # expr min lq mean median uq max neval
          # Sotos 2096.795 2127.373 2288.15768 2152.6795 2425.4740 3071.684 100
          # Ronak 30.127 33.440 42.54770 37.2055 49.4080 101.827 100
          # Wimpel 13.557 15.063 17.65734 16.1175 18.5285 38.261 100
          # WimpelMarkus 7.532 8.737 12.60520 10.0925 15.9680 45.491 100





          share|improve this answer


























          • I think you can save a couple of rev's here: vec[rev(cumsum(rev(replace(vec, is.na(vec), 0))) < 20)]. This might give a further speed-up.

            – markus
            4 hours ago








          • 1





            @markus you are very very right.. I was a bit too lazy in the copy-pasting I guess... you just reduced execution time with 30-40%! (see updated benchmarks in answer)

            – Wimpel
            4 hours ago



















          0














          I would go with Reduce



          vec[Reduce(f = "+", x = vec, accumulate = T, right = T) < 20]
          ##[1] 1 8 2 5


          Alternatively, define Reduce with function sum with the conditional argument na.rm = T in order to hanlde NAs if desired:



          vec2 <- c(3, 2, NA, 4, 5, 1, 2, 3, 4, 9, NA, 1, 2)
          vec2[Reduce(f = function(a,b) sum(a, b, na.rm = T), x = vec2, accumulate = TRUE, right = T) < 20]
          ##[1] 3 4 9 NA 1 2


          I find the Reduce option to start from right (end of the integer vector), and hence not having to reverse it first, convenient.






          share|improve this answer

























            Your Answer






            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "1"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });






            Hanna Dup is a new contributor. Be nice, and check out our Code of Conduct.










            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54212081%2fhow-to-keep-dropping-the-first-value-until-the-sum-of-the-vector-is-less-than-2%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            4 Answers
            4






            active

            oldest

            votes








            4 Answers
            4






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            8














            You need to remove the first value each time, so your while loop should be,



            while (sum(x, na.rm = TRUE) >= 20) {
            x <- x[-1]
            }

            #[1] 1 8 2 5





            share|improve this answer





















            • 1





              From the OP's post, might look like their actual data has NA's in it? If so, remember to define sum(x, na.rm = TRUE)

              – Khaynes
              5 hours ago











            • Good eye! Thanks

              – Sotos
              5 hours ago






            • 3





              Can the downvoter explain please? I went with while to point out OP's mistake! Downvote is at the very least biased

              – Sotos
              5 hours ago


















            8














            You need to remove the first value each time, so your while loop should be,



            while (sum(x, na.rm = TRUE) >= 20) {
            x <- x[-1]
            }

            #[1] 1 8 2 5





            share|improve this answer





















            • 1





              From the OP's post, might look like their actual data has NA's in it? If so, remember to define sum(x, na.rm = TRUE)

              – Khaynes
              5 hours ago











            • Good eye! Thanks

              – Sotos
              5 hours ago






            • 3





              Can the downvoter explain please? I went with while to point out OP's mistake! Downvote is at the very least biased

              – Sotos
              5 hours ago
















            8












            8








            8







            You need to remove the first value each time, so your while loop should be,



            while (sum(x, na.rm = TRUE) >= 20) {
            x <- x[-1]
            }

            #[1] 1 8 2 5





            share|improve this answer















            You need to remove the first value each time, so your while loop should be,



            while (sum(x, na.rm = TRUE) >= 20) {
            x <- x[-1]
            }

            #[1] 1 8 2 5






            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited 5 hours ago

























            answered 5 hours ago









            SotosSotos

            28.8k51640




            28.8k51640








            • 1





              From the OP's post, might look like their actual data has NA's in it? If so, remember to define sum(x, na.rm = TRUE)

              – Khaynes
              5 hours ago











            • Good eye! Thanks

              – Sotos
              5 hours ago






            • 3





              Can the downvoter explain please? I went with while to point out OP's mistake! Downvote is at the very least biased

              – Sotos
              5 hours ago
















            • 1





              From the OP's post, might look like their actual data has NA's in it? If so, remember to define sum(x, na.rm = TRUE)

              – Khaynes
              5 hours ago











            • Good eye! Thanks

              – Sotos
              5 hours ago






            • 3





              Can the downvoter explain please? I went with while to point out OP's mistake! Downvote is at the very least biased

              – Sotos
              5 hours ago










            1




            1





            From the OP's post, might look like their actual data has NA's in it? If so, remember to define sum(x, na.rm = TRUE)

            – Khaynes
            5 hours ago





            From the OP's post, might look like their actual data has NA's in it? If so, remember to define sum(x, na.rm = TRUE)

            – Khaynes
            5 hours ago













            Good eye! Thanks

            – Sotos
            5 hours ago





            Good eye! Thanks

            – Sotos
            5 hours ago




            3




            3





            Can the downvoter explain please? I went with while to point out OP's mistake! Downvote is at the very least biased

            – Sotos
            5 hours ago







            Can the downvoter explain please? I went with while to point out OP's mistake! Downvote is at the very least biased

            – Sotos
            5 hours ago















            7














            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






            share|improve this answer


























            • I think this is the fastest solution so far which of course matters only on a larger vector.

              – Phann
              5 hours ago











            • @Phann or one a large number of small vectors :).

              – snoram
              5 hours ago











            • FYI, you should also handle NA's somewhere in there. Good idea btw :)

              – Sotos
              5 hours ago











            • I don't know why but when I tried your code, the output is integer(0)

              – Hanna Dup
              5 hours ago











            • @HannaDup must be because of NAs you may take a look at the updated answer now.

              – Ronak Shah
              5 hours ago
















            7














            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






            share|improve this answer


























            • I think this is the fastest solution so far which of course matters only on a larger vector.

              – Phann
              5 hours ago











            • @Phann or one a large number of small vectors :).

              – snoram
              5 hours ago











            • FYI, you should also handle NA's somewhere in there. Good idea btw :)

              – Sotos
              5 hours ago











            • I don't know why but when I tried your code, the output is integer(0)

              – Hanna Dup
              5 hours ago











            • @HannaDup must be because of NAs you may take a look at the updated answer now.

              – Ronak Shah
              5 hours ago














            7












            7








            7







            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






            share|improve this answer















            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







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited 5 hours ago

























            answered 6 hours ago









            Ronak ShahRonak Shah

            34.8k103855




            34.8k103855













            • I think this is the fastest solution so far which of course matters only on a larger vector.

              – Phann
              5 hours ago











            • @Phann or one a large number of small vectors :).

              – snoram
              5 hours ago











            • FYI, you should also handle NA's somewhere in there. Good idea btw :)

              – Sotos
              5 hours ago











            • I don't know why but when I tried your code, the output is integer(0)

              – Hanna Dup
              5 hours ago











            • @HannaDup must be because of NAs you may take a look at the updated answer now.

              – Ronak Shah
              5 hours ago



















            • I think this is the fastest solution so far which of course matters only on a larger vector.

              – Phann
              5 hours ago











            • @Phann or one a large number of small vectors :).

              – snoram
              5 hours ago











            • FYI, you should also handle NA's somewhere in there. Good idea btw :)

              – Sotos
              5 hours ago











            • I don't know why but when I tried your code, the output is integer(0)

              – Hanna Dup
              5 hours ago











            • @HannaDup must be because of NAs you may take a look at the updated answer now.

              – Ronak Shah
              5 hours ago

















            I think this is the fastest solution so far which of course matters only on a larger vector.

            – Phann
            5 hours ago





            I think this is the fastest solution so far which of course matters only on a larger vector.

            – Phann
            5 hours ago













            @Phann or one a large number of small vectors :).

            – snoram
            5 hours ago





            @Phann or one a large number of small vectors :).

            – snoram
            5 hours ago













            FYI, you should also handle NA's somewhere in there. Good idea btw :)

            – Sotos
            5 hours ago





            FYI, you should also handle NA's somewhere in there. Good idea btw :)

            – Sotos
            5 hours ago













            I don't know why but when I tried your code, the output is integer(0)

            – Hanna Dup
            5 hours ago





            I don't know why but when I tried your code, the output is integer(0)

            – Hanna Dup
            5 hours ago













            @HannaDup must be because of NAs you may take a look at the updated answer now.

            – Ronak Shah
            5 hours ago





            @HannaDup must be because of NAs you may take a look at the updated answer now.

            – Ronak Shah
            5 hours ago











            4














            base solution without loops

            not my most readable code ever, but it's pretty fast (see benchmarking below)



            rev( rev(vec)[cumsum( replace( rev(vec), is.na( rev(vec) ), 0 ) ) < 20] )
            #[1] 1 8 2 5


            note: 'borrowed' the NA-handling from @Ronak's answer



            sample data
            vec = c(3, 2, NA, 4, 5, 1, 2, 3, 4, 9, NA, 1, 2)



            benchmarks



            microbenchmark::microbenchmark(
            Sotos = {
            while (sum(vec, na.rm = TRUE) >= 20) {
            vec <- vec[-1]
            }
            },
            Ronak = tail(vec, sum(cumsum(replace(rev(vec), is.na(rev(vec)), 0)) < 20)),
            Wimpel = rev( rev(vec)[cumsum( replace( rev(vec), is.na( rev(vec) ), 0 ) ) < 20]),
            WimpelMarkus = vec[rev(cumsum(rev(replace(vec, is.na(vec), 0))) < 20)]
            )


            # Unit: microseconds
            # expr min lq mean median uq max neval
            # Sotos 2096.795 2127.373 2288.15768 2152.6795 2425.4740 3071.684 100
            # Ronak 30.127 33.440 42.54770 37.2055 49.4080 101.827 100
            # Wimpel 13.557 15.063 17.65734 16.1175 18.5285 38.261 100
            # WimpelMarkus 7.532 8.737 12.60520 10.0925 15.9680 45.491 100





            share|improve this answer


























            • I think you can save a couple of rev's here: vec[rev(cumsum(rev(replace(vec, is.na(vec), 0))) < 20)]. This might give a further speed-up.

              – markus
              4 hours ago








            • 1





              @markus you are very very right.. I was a bit too lazy in the copy-pasting I guess... you just reduced execution time with 30-40%! (see updated benchmarks in answer)

              – Wimpel
              4 hours ago
















            4














            base solution without loops

            not my most readable code ever, but it's pretty fast (see benchmarking below)



            rev( rev(vec)[cumsum( replace( rev(vec), is.na( rev(vec) ), 0 ) ) < 20] )
            #[1] 1 8 2 5


            note: 'borrowed' the NA-handling from @Ronak's answer



            sample data
            vec = c(3, 2, NA, 4, 5, 1, 2, 3, 4, 9, NA, 1, 2)



            benchmarks



            microbenchmark::microbenchmark(
            Sotos = {
            while (sum(vec, na.rm = TRUE) >= 20) {
            vec <- vec[-1]
            }
            },
            Ronak = tail(vec, sum(cumsum(replace(rev(vec), is.na(rev(vec)), 0)) < 20)),
            Wimpel = rev( rev(vec)[cumsum( replace( rev(vec), is.na( rev(vec) ), 0 ) ) < 20]),
            WimpelMarkus = vec[rev(cumsum(rev(replace(vec, is.na(vec), 0))) < 20)]
            )


            # Unit: microseconds
            # expr min lq mean median uq max neval
            # Sotos 2096.795 2127.373 2288.15768 2152.6795 2425.4740 3071.684 100
            # Ronak 30.127 33.440 42.54770 37.2055 49.4080 101.827 100
            # Wimpel 13.557 15.063 17.65734 16.1175 18.5285 38.261 100
            # WimpelMarkus 7.532 8.737 12.60520 10.0925 15.9680 45.491 100





            share|improve this answer


























            • I think you can save a couple of rev's here: vec[rev(cumsum(rev(replace(vec, is.na(vec), 0))) < 20)]. This might give a further speed-up.

              – markus
              4 hours ago








            • 1





              @markus you are very very right.. I was a bit too lazy in the copy-pasting I guess... you just reduced execution time with 30-40%! (see updated benchmarks in answer)

              – Wimpel
              4 hours ago














            4












            4








            4







            base solution without loops

            not my most readable code ever, but it's pretty fast (see benchmarking below)



            rev( rev(vec)[cumsum( replace( rev(vec), is.na( rev(vec) ), 0 ) ) < 20] )
            #[1] 1 8 2 5


            note: 'borrowed' the NA-handling from @Ronak's answer



            sample data
            vec = c(3, 2, NA, 4, 5, 1, 2, 3, 4, 9, NA, 1, 2)



            benchmarks



            microbenchmark::microbenchmark(
            Sotos = {
            while (sum(vec, na.rm = TRUE) >= 20) {
            vec <- vec[-1]
            }
            },
            Ronak = tail(vec, sum(cumsum(replace(rev(vec), is.na(rev(vec)), 0)) < 20)),
            Wimpel = rev( rev(vec)[cumsum( replace( rev(vec), is.na( rev(vec) ), 0 ) ) < 20]),
            WimpelMarkus = vec[rev(cumsum(rev(replace(vec, is.na(vec), 0))) < 20)]
            )


            # Unit: microseconds
            # expr min lq mean median uq max neval
            # Sotos 2096.795 2127.373 2288.15768 2152.6795 2425.4740 3071.684 100
            # Ronak 30.127 33.440 42.54770 37.2055 49.4080 101.827 100
            # Wimpel 13.557 15.063 17.65734 16.1175 18.5285 38.261 100
            # WimpelMarkus 7.532 8.737 12.60520 10.0925 15.9680 45.491 100





            share|improve this answer















            base solution without loops

            not my most readable code ever, but it's pretty fast (see benchmarking below)



            rev( rev(vec)[cumsum( replace( rev(vec), is.na( rev(vec) ), 0 ) ) < 20] )
            #[1] 1 8 2 5


            note: 'borrowed' the NA-handling from @Ronak's answer



            sample data
            vec = c(3, 2, NA, 4, 5, 1, 2, 3, 4, 9, NA, 1, 2)



            benchmarks



            microbenchmark::microbenchmark(
            Sotos = {
            while (sum(vec, na.rm = TRUE) >= 20) {
            vec <- vec[-1]
            }
            },
            Ronak = tail(vec, sum(cumsum(replace(rev(vec), is.na(rev(vec)), 0)) < 20)),
            Wimpel = rev( rev(vec)[cumsum( replace( rev(vec), is.na( rev(vec) ), 0 ) ) < 20]),
            WimpelMarkus = vec[rev(cumsum(rev(replace(vec, is.na(vec), 0))) < 20)]
            )


            # Unit: microseconds
            # expr min lq mean median uq max neval
            # Sotos 2096.795 2127.373 2288.15768 2152.6795 2425.4740 3071.684 100
            # Ronak 30.127 33.440 42.54770 37.2055 49.4080 101.827 100
            # Wimpel 13.557 15.063 17.65734 16.1175 18.5285 38.261 100
            # WimpelMarkus 7.532 8.737 12.60520 10.0925 15.9680 45.491 100






            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited 4 hours ago

























            answered 5 hours ago









            WimpelWimpel

            4,585321




            4,585321













            • I think you can save a couple of rev's here: vec[rev(cumsum(rev(replace(vec, is.na(vec), 0))) < 20)]. This might give a further speed-up.

              – markus
              4 hours ago








            • 1





              @markus you are very very right.. I was a bit too lazy in the copy-pasting I guess... you just reduced execution time with 30-40%! (see updated benchmarks in answer)

              – Wimpel
              4 hours ago



















            • I think you can save a couple of rev's here: vec[rev(cumsum(rev(replace(vec, is.na(vec), 0))) < 20)]. This might give a further speed-up.

              – markus
              4 hours ago








            • 1





              @markus you are very very right.. I was a bit too lazy in the copy-pasting I guess... you just reduced execution time with 30-40%! (see updated benchmarks in answer)

              – Wimpel
              4 hours ago

















            I think you can save a couple of rev's here: vec[rev(cumsum(rev(replace(vec, is.na(vec), 0))) < 20)]. This might give a further speed-up.

            – markus
            4 hours ago







            I think you can save a couple of rev's here: vec[rev(cumsum(rev(replace(vec, is.na(vec), 0))) < 20)]. This might give a further speed-up.

            – markus
            4 hours ago






            1




            1





            @markus you are very very right.. I was a bit too lazy in the copy-pasting I guess... you just reduced execution time with 30-40%! (see updated benchmarks in answer)

            – Wimpel
            4 hours ago





            @markus you are very very right.. I was a bit too lazy in the copy-pasting I guess... you just reduced execution time with 30-40%! (see updated benchmarks in answer)

            – Wimpel
            4 hours ago











            0














            I would go with Reduce



            vec[Reduce(f = "+", x = vec, accumulate = T, right = T) < 20]
            ##[1] 1 8 2 5


            Alternatively, define Reduce with function sum with the conditional argument na.rm = T in order to hanlde NAs if desired:



            vec2 <- c(3, 2, NA, 4, 5, 1, 2, 3, 4, 9, NA, 1, 2)
            vec2[Reduce(f = function(a,b) sum(a, b, na.rm = T), x = vec2, accumulate = TRUE, right = T) < 20]
            ##[1] 3 4 9 NA 1 2


            I find the Reduce option to start from right (end of the integer vector), and hence not having to reverse it first, convenient.






            share|improve this answer






























              0














              I would go with Reduce



              vec[Reduce(f = "+", x = vec, accumulate = T, right = T) < 20]
              ##[1] 1 8 2 5


              Alternatively, define Reduce with function sum with the conditional argument na.rm = T in order to hanlde NAs if desired:



              vec2 <- c(3, 2, NA, 4, 5, 1, 2, 3, 4, 9, NA, 1, 2)
              vec2[Reduce(f = function(a,b) sum(a, b, na.rm = T), x = vec2, accumulate = TRUE, right = T) < 20]
              ##[1] 3 4 9 NA 1 2


              I find the Reduce option to start from right (end of the integer vector), and hence not having to reverse it first, convenient.






              share|improve this answer




























                0












                0








                0







                I would go with Reduce



                vec[Reduce(f = "+", x = vec, accumulate = T, right = T) < 20]
                ##[1] 1 8 2 5


                Alternatively, define Reduce with function sum with the conditional argument na.rm = T in order to hanlde NAs if desired:



                vec2 <- c(3, 2, NA, 4, 5, 1, 2, 3, 4, 9, NA, 1, 2)
                vec2[Reduce(f = function(a,b) sum(a, b, na.rm = T), x = vec2, accumulate = TRUE, right = T) < 20]
                ##[1] 3 4 9 NA 1 2


                I find the Reduce option to start from right (end of the integer vector), and hence not having to reverse it first, convenient.






                share|improve this answer















                I would go with Reduce



                vec[Reduce(f = "+", x = vec, accumulate = T, right = T) < 20]
                ##[1] 1 8 2 5


                Alternatively, define Reduce with function sum with the conditional argument na.rm = T in order to hanlde NAs if desired:



                vec2 <- c(3, 2, NA, 4, 5, 1, 2, 3, 4, 9, NA, 1, 2)
                vec2[Reduce(f = function(a,b) sum(a, b, na.rm = T), x = vec2, accumulate = TRUE, right = T) < 20]
                ##[1] 3 4 9 NA 1 2


                I find the Reduce option to start from right (end of the integer vector), and hence not having to reverse it first, convenient.







                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited 3 hours ago

























                answered 3 hours ago









                Patrik_PPatrik_P

                1,92721225




                1,92721225






















                    Hanna Dup is a new contributor. Be nice, and check out our Code of Conduct.










                    draft saved

                    draft discarded


















                    Hanna Dup is a new contributor. Be nice, and check out our Code of Conduct.













                    Hanna Dup is a new contributor. Be nice, and check out our Code of Conduct.












                    Hanna Dup is a new contributor. Be nice, and check out our Code of Conduct.
















                    Thanks for contributing an answer to Stack Overflow!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54212081%2fhow-to-keep-dropping-the-first-value-until-the-sum-of-the-vector-is-less-than-2%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    Polycentropodidae

                    Magento 2 Error message: Invalid state change requested

                    Paulmy