Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

generate column values with multiple conditions in R

I have a dataframe z and I want to create the new column based on the values of two old columns of z. Following is the process:

>z<-cbind(x=1:10,y=11:20,t=21:30)
> z<-as.data.frame(z)
>z
    x  y  t
1   1 11 21
2   2 12 22
3   3 13 23
4   4 14 24
5   5 15 25
6   6 16 26
7   7 17 27
8   8 18 28
9   9 19 29
10 10 20 30

# generate the column q which is equal to the values of column t times 4 if x=3 and for other values of x, it is equal to the values of column t.

for (i in 1:nrow(z)){
  z$q[i]=if (z$x[i]==4) 4*z$t[i] else z$t[i]}

But, my problem is that I want to apply multiple conditions:

For example, I want to get something like this:

(If x=2, q=t*2; x=4, q=t*4; x=7, q=t*3; for other it is equal to t) 

> z
   x  y  t  q
1   1 11 21 21
2   2 12 22 44
3   3 13 23 23
4   4 14 24 96
5   5 15 25 25
6   6 16 26 26
7   7 17 27 81
8   8 18 28 28
9   9 19 29 29
10 10 20 30 30

How do I get the second output using the loops or any other method?

like image 599
Metrics Avatar asked Dec 31 '12 20:12

Metrics


1 Answers

By building a nested ifelse functional by recursion, you can get the benefits of both solutions offered so far: ifelse is fast and can work with any type of data, while @Matthew's solution is more functional yet limited to integers and potentially slow.

decode <- function(x, search, replace, default = NULL) {

   # build a nested ifelse function by recursion
   decode.fun <- function(search, replace, default = NULL)
      if (length(search) == 0) {
         function(x) if (is.null(default)) x else rep(default, length(x))
      } else {
         function(x) ifelse(x == search[1], replace[1],
                                            decode.fun(tail(search, -1),
                                                       tail(replace, -1),
                                                       default)(x))
      }

   return(decode.fun(search, replace, default)(x))
}

Note how the decode function is named after the SQL function. I wish a function like this made it to the base R package... Here are a couple examples illustrating its usage:

decode(x = 1:5, search = 3, replace = -1)
# [1]  1  2 -1  4  5
decode(x = 1:5, search = c(2, 4), replace = c(20, 40), default = 3)
# [1] 3 20  3  40  3

For your particular problem:

transform(z, q = decode(x, search = c(2,4,7), replace = c(2,4,3), default = 1) * t)

#    x  y  t  q
# 1   1 11 21 21
# 2   2 12 22 44
# 3   3 13 23 23
# 4   4 14 24 96
# 5   5 15 25 25
# 6   6 16 26 26
# 7   7 17 27 81
# 8   8 18 28 28
# 9   9 19 29 29
# 10 10 20 30 30
like image 82
flodel Avatar answered Oct 11 '22 15:10

flodel