1

I'm looking for a way to extract evenly spaced elements in a vector. I'd like a general way to do this because I am trying to specify the values that I want in a plotly chart. I tried using pretty but that only seems to work with ggplot2.

I'm pretty much looking for an R version of this question that was answered for python.

Here's a sample set. This sample is a vector of 23 elements, a prime that cannot be factored.

x <- 1:23

Ideally, there would be a function that takes a number for the spacing (n) and that splits x into a subset of n evenly spaced values that also includes the first and last element. For example:

split_func(x, n = 4)
[1] 1 4 8 12 16 20 23

The output elements centered between the first and last elements and are spaced by 4, with the exception of the first/second and second-to-last/last elements.

A couple other examples:

split_func(x, n = 5)
[1] 1 5 10 15 20 23 # either this
[1] 1 4 9 14 19 23 # or this would work

split_func(1:10, n = 3)
[1] 1 3 6 9 10 # either this
[1] 1 2 5 8 10 # or this would work

split_func(1:27, n = 6)
[1] 1 5 11 17 23 27

Is there a function that does this already?

hmhensen
  • 2,974
  • 3
  • 22
  • 43
  • Maybe you can use `seq` ? `unique(c(seq(min(x), max(x), 4), max(x)))` – Ronak Shah Jul 30 '20 at 03:59
  • @RonakShah That doesn't center the values between the first and last. Just appends the last value to the previous sequence. – hmhensen Jul 30 '20 at 04:04
  • Can you give more examples of expected output for particular input values? I'm not sure it's totally clear what your expectation is for such a function. – MrFlick Jul 30 '20 at 04:08
  • @MrFlick I added some more examples to hopefully clear things up. – hmhensen Jul 30 '20 at 04:19
  • what is the logic behind this? Because in the python link you posted, it is completely different from what you have – Onyambu Jul 30 '20 at 04:28
  • 2
    in the last one, why not 1,6,12,18,24,27?? – Onyambu Jul 30 '20 at 04:34
  • @Onyambu That wouldn't work because the difference between the first two elements is not the same or within one of the difference between the last two elements. Therefore, the elements within the first and last are not centered between the first and last. – hmhensen Jul 30 '20 at 04:41
  • but you also gave this `1 5 10 15 20 23 ` and it does not satisfy what you just stated – Onyambu Jul 30 '20 at 04:44
  • Your sequence is not elaborate. Neither is it similar to the python post you provided. Sorry but you need to exlaborate more – Onyambu Jul 30 '20 at 04:46
  • @Onyambu Regarding the python question, I asked for an input more like the `by` argument in `seq` whereas the python OP asked for an input that behaves like the `length.out` argument. The basic premise of the question was the same. – hmhensen Jul 30 '20 at 04:50
  • @Onyambu On the other point, `1 5 10 15 20 23` does in fact satisfy my requirement. The difference between 1 and 5 (4) is only 0 or 1 different than the difference between 20 and 23 (3). In that case, there's no way to have those differences equal to 0 while returning a vector of integers. – hmhensen Jul 30 '20 at 04:52

1 Answers1

3

Try this:

split_func <- function(x, by) {
  r <- diff(range(x))
  out <- seq(0, r - by - 1, by = by)
  c(round(min(x) + c(0, out - 0.51 + (max(x) - max(out)) / 2), 0), max(x))
}

split_func(1:23, 4)
# [1]  1  4  8 12 16 20 23
split_func(1:23, 5)
# [1]  1  4  9 14 19 23
split_func(1:10, 3)
# [1]  1  4  7 10
split_func(1:27, 6)
# [1]  1  5 11 17 23 27
r2evans
  • 141,215
  • 6
  • 77
  • 149