2

I have a series of numbers that include both whole numbers and decimals. When I try to subset this list using a series of numbers, it ignores the decimals while subsetting. How do I get the subset range to include decimals?

Note: I understand that seqcan be used to create a sequence with different decimals (e.g., see here), but what if I want to do so using actual values from my data instead of a newly created sequence?

Is this possible?

For example:

vec <- c(-1, 0, 0.5, 0.9, 1, 1.2, 1.3, 5, 5.4, 6, 7, 9)

vec[!(vec %in% 0:2)]
 [1] -1.0  0.5  0.9  1.2  1.3  5.0  5.4  6.0  7.0  9.0

#But what I want is:
 [1] -1.0  5.0  5.4  6.0  7.0  9.0   

And

vec[!(vec %in% 1.2:5.4)]
 [1] -1.0  0.0  0.5  0.9  1.0  1.3  5.0  5.4  6.0  7.0  9.0

#But what I want is:
 [1] -1.0  0.0  0.5  0.9  1.0  6.0  7.0  9.0   
Community
  • 1
  • 1
theforestecologist
  • 4,667
  • 5
  • 54
  • 91
  • How about `vec[!(vec >= 0 & vec < 2)]`? – Vandenman Sep 19 '16 at 00:33
  • Similarly, `setdiff(vec, vec[vec>=0 & vec<2])` – SymbolixAU Sep 19 '16 at 01:04
  • 1
    I sometimes use `\`%btwn%\` <- function(a, b) a >= min(b) & a <= max(b)`, in this case it would be `vec %btwn% 0:2` – Gregor Thomas Sep 19 '16 at 01:32
  • 4
    In general, using `%in%` with decimals is a terrible idea because it is testing for equality on floats. You'll quickly run in to floating point precision problems and your next question will be a duplicate of the [Why are these numbers not equal](http://stackoverflow.com/q/9508518/903061) r-faq. For example, notice the `FALSE`s in `seq(0, 1, 0.1) %in% seq(0, 1, 0.01)`. If you want to test inclusion in a range, use `>`, `<` and the like. – Gregor Thomas Sep 19 '16 at 01:36
  • Amendment to my first comment (too late to edit). In your case it would be `vec[! vec %btwn% c(1.2, 5.4)]` – Gregor Thomas Sep 19 '16 at 01:39

2 Answers2

2

This is another approach that uses findInterval. I find that function handy in avoiding complex nested ifelse constructions. In this instance it does really seem any better than the comment suggest to use vec[!(vec >= 0 & vec < 2)].findInterval` returns a vector of numbers as long as its first input and can be used for indexing:

vec <- c(-1, 0, 0.5, 0.9, 1, 1.2, 1.3, 5, 5.4, 6, 7, 9)
vec [ findInterval(vec, c(0,2)) != 1]
#[1] -1.0  5.0  5.4  6.0  7.0  9.0

Simply cannot use : since it only supports integers.

IRTFM
  • 258,963
  • 21
  • 364
  • 487
0

Another approach using between function of dplyr package

vec[!dplyr::between(vec,0,2)]
#[1] -1.0  5.0  5.4  6.0  7.0  9.0
vec[!dplyr::between(vec,1.2,5.4)]
#[1] -1.0  0.0  0.5  0.9  1.0  6.0  7.0  9.0
user2100721
  • 3,557
  • 2
  • 20
  • 29