简体   繁体   中英

R function generating incorrect results

I am trying to get better with functions in R and I was working on a function to pull out every odd value from 100 to 500 that was divisible by 3. I got close with the function below. It keeps returning all of the values correctly but it also includes the first number in the sequence (101) when it should not. Any help would be greatly appreciated. The code I wrote is as follows:

Test=function(n){
  if(n>100){
   s=seq(from=101,to=n,by=2)
   p=c()
   for(i in seq(from=101,to=n,by=2)){
    if(any(s==i)){
      p=c(p,i)
      s=c(s[(s%%3)==0],i)
     }}
   return (p)}else{
    stop
    }}
  Test(500)

Here is a function that gets all non even multiples of 3. It's fully vectorized, no loops at all.

  1. Check if n is within the range [100, 500] .
  2. Create an integer vector N from 100 to n .
  3. Create a logical index of the elements of N that are divisible by 3 but not by 2 .
  4. Extract the elements of N that match the index i .

The main work is done in 3 code lines.

Test <- function(n){
  stopifnot(n >= 100)
  stopifnot(n <= 500)
  N <- seq_len(n)[-(1:99)]
  i <- ((N %% 3) == 0) & ((N %% 2) != 0)
  N[i]
}

Test(500)

Here is a vectorised one-liner which optionally allows you to change the lower bound from a default of 100 to anything you like. If the bounds are wrong, it returns an empty vector rather than throwing an error.

It works by creating a vector of 1:500 (or more generally, 1:n ), then testing whether each element is greater than 100 (or whichever lower bound m you set), AND whether each element is odd AND whether each element is divisible by 3. It uses the which function to return the indices of the elements that pass all the tests.

Test <- function(n, m = 100) which(1:n > m & 1:n %% 2 != 0 & 1:n %% 3 == 0)

So you can use it as specified in your question:

Test(500)
# [1] 105 111 117 123 129 135 141 147 153 159 165 171 177 183 189 195 201 207 213 219
# [21] 225 231 237 243 249 255 261 267 273 279 285 291 297 303 309 315 321 327 333 339
# [41] 345 351 357 363 369 375 381 387 393 399 405 411 417 423 429 435 441 447 453 459
# [61] 465 471 477 483 489 495

Or play around with upper and lower bounds:

Test(100, 50)
# [1] 51 57 63 69 75 81 87 93 99

Here is a function example for your objective

Test <- function(n) {
  if(n<100 | n> 500) stop("out of range")
  v <- seq(101,n,by = 2)
  na.omit(ifelse(v%%2==1 & v%%3==0,v,NA))
}
  • stop() is called when your n is out of range [100,500]
  • ifelse() outputs desired odd values + NA
  • na.omit filters out NA and produce the final results

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM