Jack Armstrong
Jack Armstrong

Reputation: 1249

How to write a function whose input is a vector and output is a character vector based on quantile information

I am writing a funcion whose input is a vector and output is a character vector of three levels: Below Avg, Avg, and Above Avg. I would like the character vector to be calucalted based on the 1st and 3rd quantiles of the vector given. When I call my function, only Below Avg returns which I understand why it returns, but do not know how to fix. Ideally I would like a new vector such that Below Avg corresponds to the values below the 1st quantile, Above Avg corresponds to values above the 3rd quantile, and Avg is everything in between.

x<-c(1:10)
label_scale<-function(vecrr){
  lq<-quantile(vecrr,0.25)
  uq<-quantile(vecrr,0.75)
  if(vecrr<=lq){
    k<-'Below Avg.'
  } else if(vecrr>=uq){
    k<-'Above Avg.'
  } else{
    k<-'Avg.'}
  return(k)
}
y<-mapply(label_scale,x)
z<-sapply(x,label_scale)

Upvotes: 0

Views: 163

Answers (2)

rookie
rookie

Reputation: 681

I would use cut and quantile in this situation:

x <- c(1:10)

x.char <- cut(x, quantile(x, c(0,.25,.75,1)), include.lowest = T, labels = c('Below Avg.', 'Avg.','Above Avg.'))

x.char
[1] Below Avg. Below Avg. Below Avg. Avg. Avg. Avg. Avg.      
[8] Above Avg. Above Avg. Above Avg.
Levels: Below Avg. Avg. Above Avg.

Upvotes: 0

AntoniosK
AntoniosK

Reputation: 16121

Your problem is that you apply your function to each one of the elements of your vector and by default a given value is always equal to the quantile of that value and your process will return Below Avg for each one of the vector elements. (Eg. x == quantile(x, 0.25) will always return TRUE).

You should use ifelse inside your function, which is vectorised:

# example vector
x<-c(1:10)

# function
label_scale<-function(vecrr){
  lq<-quantile(vecrr,0.25)
  uq<-quantile(vecrr,0.75)

ifelse(vecrr<=lq, 'Below Avg.', ifelse(vecrr>=uq, 'Above Avg.', 'Avg.'))  

}

# use function on a vector
label_scale(x)

# [1] "Below Avg." "Below Avg." "Below Avg." "Avg."       "Avg."       "Avg."       "Avg."       "Above Avg."
# [9] "Above Avg." "Above Avg."

Upvotes: 1

Related Questions