Greetings: I am looking for a way to avoid using the ifelse function for constructing a new variable. More specifically, assume I have a set of variables with scores ranging from 1 to 30. set.seed(12345) x <- c(1:30) x1 <- sample(x, 15, replace = TRUE) x2 <- sample(x, 15, replace = TRUE) x3 <- sample(x, 15, replace = TRUE) x4 <- sample(x, 15, replace = TRUE) I want to construct a dichotomous variable that tests whether any of the variables contains the value 1. newVar <-ifelse(x1 == 1 | x2 == 1 | x3 == 1 | x4 == 1, 1, 0) I want to avoid the ifelse function because I have a number of large variable lists that will require new variables to be created. I'm sure there is a simple way to do this, but I haven't had any luck with my search! Thanks in advance. Brian
alternative to ifelse
9 messages · Brian Perron, Richard M. Heiberger, Enrico Schumann +3 more
An embedded and charset-unspecified text was scrubbed... Name: not available URL: <https://stat.ethz.ch/pipermail/r-help/attachments/20130619/622f2472/attachment.pl>
On Wed, 19 Jun 2013, Brian Perron <beperron at umich.edu> writes:
Greetings: I am looking for a way to avoid using the ifelse function for constructing a new variable. More specifically, assume I have a set of variables with scores ranging from 1 to 30. set.seed(12345) x <- c(1:30) x1 <- sample(x, 15, replace = TRUE) x2 <- sample(x, 15, replace = TRUE) x3 <- sample(x, 15, replace = TRUE) x4 <- sample(x, 15, replace = TRUE) I want to construct a dichotomous variable that tests whether any of the variables contains the value 1. newVar <-ifelse(x1 == 1 | x2 == 1 | x3 == 1 | x4 == 1, 1, 0) I want to avoid the ifelse function because I have a number of large variable lists that will require new variables to be created. I'm sure there is a simple way to do this, but I haven't had any luck with my search! Thanks in advance. Brian
Hi Brian,
put all your x into a matrix and use apply:
X <- cbind(x1, x2, x3, x4)
apply(X, 1, function(x) if (any(x == 1L)) 1 else 0)
## [1] 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0
or, since TRUE and FALSE evaluate to 1 and 0 when coerced to numeric:
as.integer(apply(X, 1, function(x) any(x == 1L)))
## [1] 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0
Regards,
Enrico
Enrico Schumann Lucerne, Switzerland http://enricoschumann.net
On Jun 19, 2013, at 8:24 AM, Brian Perron <beperron at umich.edu> wrote:
Greetings: I am looking for a way to avoid using the ifelse function for constructing a new variable. More specifically, assume I have a set of variables with scores ranging from 1 to 30. set.seed(12345) x <- c(1:30) x1 <- sample(x, 15, replace = TRUE) x2 <- sample(x, 15, replace = TRUE) x3 <- sample(x, 15, replace = TRUE) x4 <- sample(x, 15, replace = TRUE) I want to construct a dichotomous variable that tests whether any of the variables contains the value 1. newVar <-ifelse(x1 == 1 | x2 == 1 | x3 == 1 | x4 == 1, 1, 0) I want to avoid the ifelse function because I have a number of large variable lists that will require new variables to be created. I'm sure there is a simple way to do this, but I haven't had any luck with my search! Thanks in advance. Brian
If each of the vectors will be of the same length, create a matrix that contains each one as a column: set.seed(12345) x <- c(1:30) x1 <- sample(x, 15, replace = TRUE) x2 <- sample(x, 15, replace = TRUE) x3 <- sample(x, 15, replace = TRUE) x4 <- sample(x, 15, replace = TRUE)
cbind(x1, x2, x3, x4)
x1 x2 x3 x4 [1,] 22 14 24 10 [2,] 27 12 1 2 [3,] 23 13 6 2 [4,] 27 6 21 2 [5,] 14 29 12 19 [6,] 5 14 11 29 [7,] 10 10 27 25 [8,] 16 29 28 10 [9,] 22 22 19 7 [10,] 30 20 5 22 [11,] 2 12 24 15 [12,] 5 21 13 22 [13,] 23 17 28 3 [14,] 1 7 24 14 [15,] 12 15 8 8 Then you can use:
rowSums(cbind(x1, x2, x3, x4) == 1)
[1] 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 which gets you the same result as:
ifelse(x1 == 1 | x2 == 1 | x3 == 1 | x4 == 1, 1, 0)
[1] 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 Regards, Marc Schwartz
On Jun 19, 2013, at 8:24 AM, Brian Perron <beperron at umich.edu> wrote:
Greetings: I am looking for a way to avoid using the ifelse function for constructing a new variable. More specifically, assume I have a set of variables with scores ranging from 1 to 30. set.seed(12345) x <- c(1:30) x1 <- sample(x, 15, replace = TRUE) x2 <- sample(x, 15, replace = TRUE) x3 <- sample(x, 15, replace = TRUE) x4 <- sample(x, 15, replace = TRUE) I want to construct a dichotomous variable that tests whether any of the variables contains the value 1. newVar <-ifelse(x1 == 1 | x2 == 1 | x3 == 1 | x4 == 1, 1, 0) I want to avoid the ifelse function because I have a number of large variable lists that will require new variables to be created. I'm sure there is a simple way to do this, but I haven't had any luck with my search! Thanks in advance. Brian
If each of the vectors will be of the same length, create a matrix that contains each one as a column: set.seed(12345) x <- c(1:30) x1 <- sample(x, 15, replace = TRUE) x2 <- sample(x, 15, replace = TRUE) x3 <- sample(x, 15, replace = TRUE) x4 <- sample(x, 15, replace = TRUE)
cbind(x1, x2, x3, x4)
x1 x2 x3 x4 [1,] 22 14 24 10 [2,] 27 12 1 2 [3,] 23 13 6 2 [4,] 27 6 21 2 [5,] 14 29 12 19 [6,] 5 14 11 29 [7,] 10 10 27 25 [8,] 16 29 28 10 [9,] 22 22 19 7 [10,] 30 20 5 22 [11,] 2 12 24 15 [12,] 5 21 13 22 [13,] 23 17 28 3 [14,] 1 7 24 14 [15,] 12 15 8 8 Then you can use:
rowSums(cbind(x1, x2, x3, x4) == 1)
[1] 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 which gets you the same result as:
ifelse(x1 == 1 | x2 == 1 | x3 == 1 | x4 == 1, 1, 0)
[1] 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 Regards, Marc Schwartz
On Jun 19, 2013, at 1:23 PM, Marc Schwartz <marc_schwartz at me.com> wrote:
On Jun 19, 2013, at 8:24 AM, Brian Perron <beperron at umich.edu> wrote:
Greetings: I am looking for a way to avoid using the ifelse function for constructing a new variable. More specifically, assume I have a set of variables with scores ranging from 1 to 30. set.seed(12345) x <- c(1:30) x1 <- sample(x, 15, replace = TRUE) x2 <- sample(x, 15, replace = TRUE) x3 <- sample(x, 15, replace = TRUE) x4 <- sample(x, 15, replace = TRUE) I want to construct a dichotomous variable that tests whether any of the variables contains the value 1. newVar <-ifelse(x1 == 1 | x2 == 1 | x3 == 1 | x4 == 1, 1, 0) I want to avoid the ifelse function because I have a number of large variable lists that will require new variables to be created. I'm sure there is a simple way to do this, but I haven't had any luck with my search! Thanks in advance. Brian
If each of the vectors will be of the same length, create a matrix that contains each one as a column: set.seed(12345) x <- c(1:30) x1 <- sample(x, 15, replace = TRUE) x2 <- sample(x, 15, replace = TRUE) x3 <- sample(x, 15, replace = TRUE) x4 <- sample(x, 15, replace = TRUE)
cbind(x1, x2, x3, x4)
x1 x2 x3 x4 [1,] 22 14 24 10 [2,] 27 12 1 2 [3,] 23 13 6 2 [4,] 27 6 21 2 [5,] 14 29 12 19 [6,] 5 14 11 29 [7,] 10 10 27 25 [8,] 16 29 28 10 [9,] 22 22 19 7 [10,] 30 20 5 22 [11,] 2 12 24 15 [12,] 5 21 13 22 [13,] 23 17 28 3 [14,] 1 7 24 14 [15,] 12 15 8 8 Then you can use:
rowSums(cbind(x1, x2, x3, x4) == 1)
[1] 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 which gets you the same result as:
ifelse(x1 == 1 | x2 == 1 | x3 == 1 | x4 == 1, 1, 0)
[1] 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0
Actually, correction. That works in the case where only one of the values in the row is a 1, which happened to fit the example data. If there is a chance that more than one value in a row may be a 1, it returns a value equal to the number of 1's found. Thus, a more generic approach, I believe, would be:
sign(rowSums(cbind(x1, x2, x3, x4) == 1))
[1] 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 Regards, Marc
On Jun 19, 2013, at 1:23 PM, Marc Schwartz <marc_schwartz at me.com> wrote:
On Jun 19, 2013, at 8:24 AM, Brian Perron <beperron at umich.edu> wrote:
Greetings: I am looking for a way to avoid using the ifelse function for constructing a new variable. More specifically, assume I have a set of variables with scores ranging from 1 to 30. set.seed(12345) x <- c(1:30) x1 <- sample(x, 15, replace = TRUE) x2 <- sample(x, 15, replace = TRUE) x3 <- sample(x, 15, replace = TRUE) x4 <- sample(x, 15, replace = TRUE) I want to construct a dichotomous variable that tests whether any of the variables contains the value 1. newVar <-ifelse(x1 == 1 | x2 == 1 | x3 == 1 | x4 == 1, 1, 0) I want to avoid the ifelse function because I have a number of large variable lists that will require new variables to be created. I'm sure there is a simple way to do this, but I haven't had any luck with my search! Thanks in advance. Brian
If each of the vectors will be of the same length, create a matrix that contains each one as a column: set.seed(12345) x <- c(1:30) x1 <- sample(x, 15, replace = TRUE) x2 <- sample(x, 15, replace = TRUE) x3 <- sample(x, 15, replace = TRUE) x4 <- sample(x, 15, replace = TRUE)
cbind(x1, x2, x3, x4)
x1 x2 x3 x4 [1,] 22 14 24 10 [2,] 27 12 1 2 [3,] 23 13 6 2 [4,] 27 6 21 2 [5,] 14 29 12 19 [6,] 5 14 11 29 [7,] 10 10 27 25 [8,] 16 29 28 10 [9,] 22 22 19 7 [10,] 30 20 5 22 [11,] 2 12 24 15 [12,] 5 21 13 22 [13,] 23 17 28 3 [14,] 1 7 24 14 [15,] 12 15 8 8 Then you can use:
rowSums(cbind(x1, x2, x3, x4) == 1)
[1] 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 which gets you the same result as:
ifelse(x1 == 1 | x2 == 1 | x3 == 1 | x4 == 1, 1, 0)
[1] 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0
Actually, correction. That works in the case where only one of the values in the row is a 1, which happened to fit the example data. If there is a chance that more than one value in a row may be a 1, it returns a value equal to the number of 1's found. Thus, a more generic approach, I believe, would be:
sign(rowSums(cbind(x1, x2, x3, x4) == 1))
[1] 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 Regards, Marc
Hi,
May bet this also helps:
set.seed(12345)
x <- c(1:30)
x1 <- sample(x, 15, replace = TRUE)
x2 <- sample(x, 15, replace = TRUE)
x3 <- sample(x, 15, replace = TRUE)
x4 <- sample(x, 15, replace = TRUE)
indx<-1+2*(x1==1)+4*(x2==1)+8*(x3==1)+16*(x4==1)
?as.numeric(indx!=1)
#[1] 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0
#Speed comparisons
set.seed(1235)
x <- c(1:1e7)
x1 <- sample(x, 1e7, replace = TRUE)
x2 <- sample(x, 1e7, replace = TRUE)
x3 <- sample(x, 1e7, replace = TRUE)
x4 <- sample(x, 1e7, replace = TRUE)
system.time(res1 <-ifelse(x1 == 1 | x2 == 1 | x3 == 1 | x4 == 1, 1, 0))
?# user? system elapsed
?# 3.740?? 0.256?? 4.003
system.time(res2<-as.numeric(x1 == 1 | x2 == 1 | x3 == 1 | x4 == 1))
# user? system elapsed
#? 0.996?? 0.076?? 1.077
system.time({indx<-1+2*(x1==1)+4*(x2==1)+8*(x3==1)+16*(x4==1)
?res3<-as.numeric(indx!=1)})
# user? system elapsed
#? 0.596?? 0.240?? 0.840
system.time(res4<-rowSums(cbind(x1, x2, x3, x4) == 1))
# user? system elapsed
#? 0.732?? 0.192?? 0.926
?
system.time(res4New<-sign(rowSums(cbind(x1, x2, x3, x4) == 1)))
?# user? system elapsed
?# 0.824?? 0.232?? 1.062
X <- cbind(x1, x2, x3, x4)
system.time({
res5<-as.integer(apply(X, 1, function(x) any(x == 1L)))})
?# user? system elapsed
#113.308?? 0.208 113.729
system.time(res6<-apply(X, 1, function(x) if (any(x == 1L)) 1 else 0))
?#user? system elapsed
# 61.660?? 0.216? 61.989
identical(res1,res6)
#[1] TRUE
identical(res1,res2)
#[1] TRUE
?identical(res1,res3)
#[1] TRUE
identical(res1,res4)
#[1] TRUE
?identical(res1,res4New)
#[1] TRUE
A.K.
----- Original Message -----
From: Brian Perron <beperron at umich.edu>
To: r-help at r-project.org
Cc:
Sent: Wednesday, June 19, 2013 9:24 AM
Subject: [R] alternative to ifelse
Greetings:
I am looking for a way to avoid using the ifelse function for
constructing a new variable.? More specifically, assume I have a set
of variables with scores ranging from 1 to 30.
set.seed(12345)
x <- c(1:30)
x1 <- sample(x, 15, replace = TRUE)
x2 <- sample(x, 15, replace = TRUE)
x3 <- sample(x, 15, replace = TRUE)
x4 <- sample(x, 15, replace = TRUE)
I want to construct a dichotomous variable that tests whether any of
the variables contains the value 1.
newVar <-ifelse(x1 == 1 | x2 == 1 | x3 == 1 | x4 == 1, 1, 0)
I want to avoid the ifelse function because I have a number of large
variable lists that will require new variables to be created.? I'm
sure there is a simple way to do this, but I haven't had any luck with
my search!
Thanks in advance.
Brian
______________________________________________
R-help at r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-help
PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
and provide commented, minimal, self-contained, reproducible code.
1 day later
Once you have this matrix: mx <- cbind(x1, x2, x3, x4)
x1 x2 x3 x4 [1,] 22 14 24 10 [2,] 27 12 1 2 [3,] 23 13 6 2 [4,] 27 6 21 2 [5,] 14 29 12 19 [6,] 5 14 11 29 [7,] 10 10 27 25 [8,] 16 29 28 10 [9,] 22 22 19 7 [10,] 30 20 5 22 [11,] 2 12 24 15 [12,] 5 21 13 22 [13,] 23 17 28 3 [14,] 1 7 24 14 [15,] 12 15 8 8
ifelse( apply(mx, 1, function(x) any(x==1)), 1, 0 )
#or
as.numeric( apply(mx, 1, function(x) any(x==1)) )
should work.
S Ellison
*******************************************************************
This email and any attachments are confidential. Any use...{{dropped:8}}