R 如何在不使用列号的情况下将函数应用于两个序列的顺序标记变量?

R 如何在不使用列号的情况下将函数应用于两个序列的顺序标记变量?,r,function,loops,repeat,R,Function,Loops,Repeat,我需要使用两组顺序标记的变量应用函数,并将新的变量集附加到数据帧。我需要在不参考代码中的列号的情况下执行此操作 更具体地说,以下是我正在尝试完成的简单任务: 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 = sam

我需要使用两组顺序标记的变量应用函数,并将新的变量集附加到数据帧。我需要在不参考代码中的列号的情况下执行此操作

更具体地说,以下是我正在尝试完成的简单任务:

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
dat
dat\u n 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
1230.66667 0.66667 0.3333333 NA
2 3 4 0 2 4 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
6121213010000000103333NA
71340024NA 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

您可以在
ifelse
上使用
矢量化
,并对其进行大量清理

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
set.seed(1)

在这种情况下,dat
Map
而不是
mappy
可能会更好,但这肯定是答案的核心。非常感谢!您认为有可能修改此代码,使其不引用列号(例如dat[1:3])?这是一个长期变化的代码的一部分,由于添加/删除变量,列号不断变化。这就是为什么我需要一个不使用列号的解决方案。@Eva-当然,类似于:
dat[grepl(^sec\\d{1,},names(dat))]
将抓取每个组。@RStudent-我把正则表达式做得更具体了一点是的,我想你的意思是这样的,它工作得很好(再次感谢!),但返回的变量名称相同?我想我以后必须更改列名。(例如,从sec1,sec2..到rel1,rel2,…):dat_n 0,x/y,NA),dat[grepl(^sec\\d{1,},names(dat))],dat[grepl(^pri\\d{1,},names(dat)))dat[grepl(^sec\\d{1,},names(dat))]谢谢!我不知道矢量化。显然,在我的实际数据集中还有其他变量,包括字符“sec”或“pri”,所以我稍微编辑了一下代码(用c(^sec.*,“^pri.*”)替换了c(^sec.*,“^pri.*))它工作得非常好!非常有用!
Vectorize
是一个助手,它将获取一个函数并用
mappy
包装它,因此这个答案与另一个答案基本相同,只是不必知道
mappy
语法
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