Search code examples
rdataframefunctionreturn-valueassign

Assign and save values based on function output in R


I'm stuck with something that should be very easy.

I have been working with a function that I want to take a vector or single column of data and output a "color" depending on which range the value falls into.

band_code <- function(x){
  x <- x[1]
  if(x < (-0.25)){color <- "cold"}
  else if(x > (-0.25) && x < (0.25)){color <- "off"}
  else if(x > (0.25) && x < (0.75)){color <- "intermediate"}
  else if(x > (0.75) && x < (1.25)){color <- "on"}
  else if(x > (1.25)){color <- "extra"}
  return(color)
}

This works well for simple, single tests:

> band_code(0.76)
[1] "on"

And this works well, using a test vector:

test <- -2:2

for (i in test){
  print(i)
  band = band_code(i)
  print(band)
}

[1] -2
[1] "cold"
[1] -1
[1] "cold"
[1] 0
[1] "off"
[1] 1
[1] "on"
[1] 2
[1] "extra"

But when I try to save the output as a column in an object, it fails:

test <- as.data.frame(test)

for (i in test){
  band = band_code(i)
  test$band <- band
}

> test
  test band
1   -2 cold
2   -1 cold
3    0 cold
4    1 cold
5    2 cold

The "band" values should be as they were before ("cold", "cold", "off", "on", "extra"), but I guess it is repeating the first "cold" all 5 times.

What about saving the output to an object causes the malfunction?

I think it has to do with the first line in the band_code function (x <- x[1]), but after many various attempts I can't get it to work.

Help, please!


Solution

  • You should use cut() for situations like this:

    test <- -2:2
    test <- as.data.frame(test)
    test$vals <- cut(test$test, breaks=c(-Inf, -.25, .25, .75, 1.25, Inf), labels=c("cold", "off", "intermediate", "on", "extra"))
    test
    #   test  vals
    # 1   -2  cold
    # 2   -1  cold
    # 3    0   off
    # 4    1    on
    # 5    2 extra