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:
&g
Based on the suggestion of Señor :
> z$q <- ifelse(z$x == 2, z$t * 2,
ifelse(z$x == 4, z$t * 4,
ifelse(z$x == 7, z$t * 3,
z$t * 1)))
> 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
I really liked the answer "dinre" posted to flodel's blog:
for (i in 1:length(data_Array)){
data_Array[i] <- switch(data_Array[i], banana="apple", orange="pineapple", "fig")
}
With warnings about reading the help page for switch
carefully for integer arguments.
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
Here is an easy solution with just one ifelse
command:
Calculate the multiplier of t
:
ifelse(z$x == 7, 3, z$x ^ (z$x %in% c(2, 4)))
The complete command:
transform(z, q = t * ifelse(x == 7, 3, x ^ (x %in% c(2, 4))))
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
You can also use match to do this. I tend to use this a lot while assigning parameters like col, pch and cex to points in scatterplots
searchfor<-c(2,4,7)
replacewith<-c(2,4,3)
# generate multiplier column
# q could also be an existing vector where you want to replace certain entries
q<-rep(1,nrow(z))
#
id<-match(z$x,searchfor)
id<-replacewith[id]
# Apply the matches to q
q[!is.na(id)]<-id[!is.na(id)]
# apply to t
z$q<-q*z$t
You can do it in
like this:
> transform(z,q=t*sapply(as.character(x),function(x) switch(x,"2"=2,"4"=4,"7"=3,1)))
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