osu-statistics
osu-statistics

Reputation: 19

function to subset n vector giving error message "incorrect number of dimensions"

I was making a function to extract a value from a vector given its position in the vector.

func_name <- function(input_vec, input_n) {
  sort(input_vec)
  if(input_n > input_vec) {
    return("Warning: input_n exceeds vector length")
  }
  else {
    return(input_vec[,c(input_n)][input_vec == input_n])
    }
}
input_vector <- c(1,2,30,40,50,60)
func_name(input, 3)

I am trying to get the output 30, such that the function extracts the third element from the vector. When I run the function, I get the following error message:

the condition has length > 1 and only the first element will be usedError in input_vec[, c(input_n)] : incorrect number of dimensions

I then read the error message and figured there might be conflicts running this with an ifelse statement so I tried the following:

find_largestN <- function(input_vec, input_n) {
  sort(input_vec) 
  if(input_n < input_vec) {   
  return(input_vec[,c(input_n)][input_vec == input_n])
  }
  else {
    break
}
}

For this, I got the following error message.

the condition has length > 1 and only the first element will be usedError in find_largestN(input_vec, 1) : 
  no loop for break/next, jumping to top level

I thought that this would have simplified it and reduced the chance of error but clearly it didn't work. Are there any recommendations to subset within an if else statement or function?

Upvotes: 0

Views: 125

Answers (2)

Skaqqs
Skaqqs

Reputation: 4140

Very close! I needed to add length() to your if statement

func_name <- function(input_vec, input_n) {
  sort(input_vec)
  if(input_n > length(input_vec)) {
    return("Warning: input_n exceeds vector length")
  }
  else {
    return(input_vec[input_n])
  }
}

Others have recommended ifelse(). That could look something like

ifelse(
   test = input_n > length(input_vec),
   yes = print("input_n exceeds vector length"),
   no = input_vec[input_n])

Upvotes: 1

monte
monte

Reputation: 1865

Firstly about the difference between ifelse and if/else.

ifelse is a vectorised method, it takes a vector as an input and produces the vector of the same length.

x = rnorm(10)
ifelse(x > 0 , "positive", "negative")
#>  [1] "positive" "negative" "positive" "positive" "negative" "negative"
#>  [7] "positive" "positive" "positive" "negative"

if(x>0) "positive" else negative
#> Warning in if (x > 0) "positive" else negative: the condition has length > 1 and
#> only the first element will be used
#> [1] "positive"

Created on 2021-07-02 by the reprex package (v0.3.0)

But in the case of if/else, if only takes length 1 logical vector. For vectors greater than length 1, the first element is used for checking the condition and a warning is thrown, as you can see from the above example.

Looking at your code, it appears you are checking the if condition to compare the length of vector with provided index. So it should be:

func_name <- function(input_vec, input_n) {
  if(length(input_vec) < input_n) {
    return("Warning: input_n exceeds vector length")
  }
  else {
    sort(input_vec)
    input_vec[input_n]
  }
}
input_vector <- c(1,2,30,40,50,60)
func_name(input_vector, 3)
#> [1] 30

Created on 2021-07-02 by the reprex package (v0.3.0)

Also note that I have put sort(input_vec) inside else as it makes sense to sort only when the condition is met, bit of optimization tip.

Upvotes: 2

Related Questions