Missing last sequence in seq() in R
Asked Answered
S

6

6

I have this example data

by<-200
to<-seq(from=by,to=35280,by=by)

Problem is that to ends at 35200 and ignore the last 80 which I need to involve in as last value. Is there any straigthforward way how to achieve it? I have tried along.with and length.out parameters but I cannot go trough.

Silsbye answered 9/2, 2015 at 21:2 Comment(2)
What is the output that you want? If you want to count from 200 to 35280 by 200s, then the function is doing what it's supposed to doTrinity
I know it does, but I ask for way how to modify it to add last value as a part of the output (even if it is not in original sequence done by parameter by). Answers below does the job.Silsbye
T
8

You can place if statement for the last element of the vector such as in the following function :

seqlast <- function (from, to, by) 
{
  vec <- do.call(what = seq, args = list(from, to, by))
  if ( tail(vec, 1) != to ) {
    return(c(vec, to))
  } else {
    return(vec)
  }
}

Then

by <- 200
to <- seqlast(from=by,to=35280,by=by)

will return

> head(to)
[1]  200  400  600  800 1000 1200
> tail(to)
[1] 34400 34600 34800 35000 35200 35280
Thigmotaxis answered 21/6, 2017 at 14:21 Comment(0)
M
6

In seq(), "The second form generates from, from+by, ..., up to the sequence value less than or equal to to." And also since 35280 is not in the requested sequence, it is not returned.

But you can use a calculation in the arguments it you wan to include the next value. Since you know the to value, assign it a name and use it.

by <- 200
out <- 35280

x <- seq(from = by, to = (out + by - out %% by), by = by)

length(x)
# [1] 177
x[length(x)]
# [1] 35400

If you want to include the to value, even if it is not in the requested sequence, you can write a little function to add it back on

seqil <- function(..., include.last = TRUE) {
    x <- do.call(seq.default, list(...))
    if(include.last) c(x, to) else x
}

by <- 200

x <- seqil(from = by, to = 35280, by = by)
tail(x)
# [1] 34400 34600 34800 35000 35200 35280
Michelemichelina answered 9/2, 2015 at 21:29 Comment(1)
Well, if I copy your second code the result is tail(x) [1] 34400 34600 34800 35000 35200 200Silsbye
B
0

First of all, seq() is behaving as it should in your example. You want something that seq() by itself will simply not deliver.

One solution (there are certainly many) is to check weather "there was anything left" at the end of your sequence and, if so, add another element to it. (Or modify the last element of your sequence, it is not exactly clear what you are trying to achieve.) Like so:

step <- 200
end <- 35280
to<-seq(from=step,to=end,by=step)

# the modulus of your end point by step
m = end%%step 

# if not zero, you have something to add to your sequence
if(m != 0) {

    # add the end point
    to = c(to, end)
}

tail(to,2)
# 35200 35280
Bdellium answered 9/2, 2015 at 21:8 Comment(3)
The solution doesn't work. Check with the following values > end <- 10 > step <- 2 > to<-seq(from=1,to=end,by=step) > m = end%%step > if(m != 0) { + + to = c(to, end) + } > > tail(to) [1] 1 3 5 7 9 > > step <- 3 > > to<-seq(from=1,to=end,by=step) > m = end%%step > > if(m != 0) { + + to = c(to, end) + } > tail(to) [1] 1 4 7 10 10Thigmotaxis
first, what you wrote there is not my solution -- my solution works for end = 10 and step = 2; second, by using your solution I am getting [1] 1 3 5 7 9. I suggest you start your code with rm(list=ls()).Bdellium
No. Your solution does not work. Let "end <- 10" and "step <- 2". the value of "m <- end %% step" is equals to 0. So you are not getting inside the your if statement. So the value of "to <- seq(from=1,to=end,by=step)" remainds "[1] 1 3 5 7 9" and does not finish with 10, which is wrong.Thigmotaxis
A
0

Whilst not solving the exact issue raised my preferred solution to this is to extend the sequence to add an additional value so that the to value is included in the sequence rather than just appending the to value at the end. This builds on the answers by both @djas and @Etienne Kintzler.

seq0 <- function(from = 1, to = 1, by = 1, incLast = TRUE){
    out = do.call(what = seq, args = list(from, to, by))
    if (incLast & to%%by != 0){
        out = c(out, tail(out, 1) + by) 
    } 
    return(out)
}

Example outputs:

> seq0(from = 0, to = 20, by = 6, incLast = FALSE)
[1]  0  6 12 18
> seq0(from = 0, to = 20, by = 6, incLast = TRUE)
[1]  0  6 12 18 24
> seq0(from = 0, to = -20, by = -6, incLast = FALSE)
[1]   0  -6 -12 -18
> seq0(from = 0, to = -20, by = -6, incLast = TRUE)
[1]   0  -6 -12 -18 -24
Antoine answered 2/3, 2019 at 2:41 Comment(0)
D
0

This is a modification of Rich Scriven answer, that does not add an extra number, when it is not necessary (as with 20)

by <- 2
out <- 21
out <- 20

x <- seq(from = 0, to = out + by*ifelse(out %% by>0,1,0) - out %% by , by = by)
x
Dichroism answered 27/1, 2020 at 3:31 Comment(0)
C
0

You can use c() to include the last number.

by<-200
c(seq(from=by,to=35280,by=by), 35280)
Clop answered 7/9, 2021 at 7:12 Comment(1)
Please add further details to expand on your answer, such as working code or documentation citations.Sapowith

© 2022 - 2024 — McMap. All rights reserved.