I need to apply a function using two sets of sequentially labelled variables and attach the new set of variables to the data frame. I need to do this without referring to the column numbers in the code.
More specifically, here is the simple task I am trying to do:
dat <- data.frame(sec1 = sample(c(0:3),10,replace=T) , sec2 = sample(c(0:4),replace=T) , sec3 = sample(c(0:4),replace=T),pri1 = sample(c(0:3),10,replace=T) , pri2 = sample(c(0:4),replace=T) , pri3 = sample(c(0:4),replace=T) )
dat$rel1 <- ifelse(dat$pri1>0,dat$sec1/dat$pri1,NA)
dat
I want to repeat the "ifelse" function shown above without typing it repeatedly for each set of variables.
I must say, I asked similar questions and received helpful answers ( eg1 and eg2 ) previously but in those case the responses either used the column number in the code, or the example was on a single set of sequentially labelled variable. I could not manage to revise the suggested code to solve this particular problem.
Any suggestion is very much appreciated.
dat_n <- cbind(dat, mapply(function(x, y) ifelse(y>0,x/y,NA) ,dat[grepl("sec",names(dat))], dat[grepl("pri",names(dat))]))
> dat_n
sec1 sec2 sec3 pri1 pri2 pri3 rel1 sec1 sec2 sec3
1 2 1 2 3 3 0 0.6666667 0.6666667 0.3333333 NA
2 3 3 4 0 2 4 NA NA 1.5000000 1.00
3 1 0 3 1 4 4 1.0000000 1.0000000 0.0000000 0.75
4 2 4 1 3 3 2 0.6666667 0.6666667 1.3333333 0.50
5 2 0 2 3 4 1 0.6666667 0.6666667 0.0000000 2.00
6 1 1 2 1 3 0 1.0000000 1.0000000 0.3333333 NA
7 1 3 4 0 2 4 NA NA 1.5000000 1.00
8 1 0 3 1 4 4 1.0000000 1.0000000 0.0000000 0.75
9 3 4 1 2 3 2 1.5000000 1.5000000 1.3333333 0.50
10 1 0 2 2 4 1 0.5000000 0.5000000 0.0000000 2.00
You could use Vectorize
on an ifelse
and clean this up a lot
set.seed(1)
dat <- data.frame(sec1 = sample(c(0:3),10,replace=T) , sec2 = sample(c(0:4),replace=T) , sec3 = sample(c(0:4),replace=T),pri1 = sample(c(0:3),10,replace=T) , pri2 = sample(c(0:4),replace=T) , pri3 = sample(c(0:4),replace=T) )
dat$rel1 <- ifelse(dat$pri1>0,dat$sec1/dat$pri1,NA)
dat
f <- Vectorize(function(x, y) ifelse(y > 0, x / y, NA))
f(dat[1:3], dat[4:6])
# sec1 sec2 sec3
# [1,] 0.3333333 0.50 0.6666667
# [2,] NA 0.00 1.0000000
# [3,] 1.0000000 1.50 NA
# [4,] NA NA 0.3333333
# [5,] 0.0000000 0.75 1.5000000
# [6,] 3.0000000 0.50 0.6666667
# [7,] NA 0.00 1.0000000
# [8,] 2.0000000 1.50 NA
# [9,] 0.6666667 NA 0.3333333
# [10,] 0.0000000 0.75 1.5000000
v <- lapply(c('sec','pri'), function(x) grep(x, names(dat)))
cbind(dat, `colnames<-`(f(dat[v[[1]]], dat[v[[2]]]), paste0('rel',1:3)))
# sec1 sec2 sec3 pri1 pri2 pri3 rel1 rel1 rel2 rel3
# 1 1 1 2 3 2 3 0.3333333 0.3333333 0.50 0.6666667
# 2 1 0 3 0 2 3 NA NA 0.00 1.0000000
# 3 2 3 4 2 2 0 1.0000000 1.0000000 1.50 NA
# 4 3 1 1 0 0 3 NA NA NA 0.3333333
# 5 0 3 3 1 4 2 0.0000000 0.0000000 0.75 1.5000000
# 6 3 1 2 1 2 3 3.0000000 3.0000000 0.50 0.6666667
# 7 3 0 3 0 2 3 NA NA 0.00 1.0000000
# 8 2 3 4 1 2 0 2.0000000 2.0000000 1.50 NA
# 9 2 1 1 3 0 3 0.6666667 0.6666667 NA 0.3333333
# 10 0 3 3 1 4 2 0.0000000 0.0000000 0.75 1.5000000
(yo dawg I heard you like to vectorize so we put some Vectorize
in your vectorized so you can Vectorize
while you vectorize)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.