我正在尝试编写一个函数,该函数采用两个列名以及每个列名的上限和/或下限,这样我就可以使用我选择的列名和边界对数据进行子集化。
以 mtcars 为例,如果我想通过说我只想要具有cyl > 4
和的行来对数据进行子集化mpg > 15
,在这种情况下,我的函数将接受两个列名cyl
和mpg
,每个列名还有两个下边界,即 4 和 15。当然,在函数中,我可以选择为其分配一个上限,以将列名(变量)保持在一定范围内。
所以我想出了类似下面的东西,一个函数,它接受您选择的两个变量名称以及每个变量的上限和/或下限。
如果我只给这个变量一个上限或下限,那么它会给我任何小于或大于这个边界的东西,如果我给函数同时给出上限和下限,它会给我返回落入该范围的行。
comb_function<-function(df,var1,var2,var1_lower=NULL,var1_upper=NULL,var2_upper=NULL,var2_lower=NULL){
var1<-enexpr(var1)
var2<-enexpr(var2)
#####for var2,if upper boundary are given by user,do this#####{
filter1<-expr(`$`(df,!!var2))<=var2_upper
#for var1, if upper boundary are given by user,do this# {
filter2<-expr(`$`(df,!!var1))<=var1_upper}
#for var 1,if lower boundary are given by user, do this#{
filter2<-expr(`$`(df,!!var1))>=var1_lower}
#for var1, if both are given by user, do this#{
filter2<-expr(`$`(df,!!var1))>=var1_lower&expr(`$`(df,!!var1))<=var1_upper}
}
#####for var2,if lower boundary are given by user,do this#####{
filter1<-expr(`$`(df,!!var2))>=var2_lower
#for var1,if upper boundary are given by user,do this#{
filter2<-expr(`$`(df,!!var1))<=var1_upper}
#for var1,if lower boundary are given by user,do this#{
filter2<-expr(`$`(df,!!var1))>=var1_lower}
#if both are given by the user,do this{
filter2<-expr(`$`(df,!!var1))>=var1_lower&expr(`$`(df,!!var1))<=var1_upper}
}
#####for var2,if both are given by user,do this#####{
filter1<-expr(`$`(df,!!var2))<=var2_upper&expr(`$`(df,!!var2))>=var2_lower
#for var1,if upper boundary are given by user,do this#{
filter2<-expr(`$`(df,!!var1))<=var1_upper}
#for var1,if lower boundary are given by user,do this#{
filter2<-expr(`$`(df,!!var1))>=var1_lower}
#if both are given by user, do this#{
filter2<-expr(`$`(df,!!var1))>=var1_lower&expr(`$`(df,!!var1))<=var1_upper}
}
output<-df%>%filter(filter1,filter2)%>%summarise(count=n(),avgcyl=mean(cyl,na.rm=TRUE))
return(output)
}
当我以 mtcars 为例调用此函数时
final1<-comb_function(df=mtcars,var1=mpg,var2=cyl,var1_lower =15,var2_lower=4,var2_upper=6)
我在 final1 中得到了 avgcrl 的 0 个计数和 NaN。所以当filter()
评估里面的内容时()
,它只会得到 FALSE,没有 TRUE,我认为这就是为什么没有返回行。
我有一个关于为什么会发生这种情况的理论。如果我这样做:
x<-expr(cyl);eval(expr(expr(`$`(mtcars,!!x))<=6))
它返回:
[1]FALSE
这显然不是我所期望的。如果我这样做:
eval(expr(`$`(mtcars,!!x)))<=6
它返回
[1] TRUE TRUE TRUE TRUE FALSE TRUE FALSE TRUE TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE FALSE TRUE TRUE TRUE TRUE FALSE
[23] FALSE FALSE FALSE TRUE TRUE TRUE FALSE TRUE FALSE TRUE
这就是我想要的filter()
函数内部的函数。所以我猜当filter()
评估里面的内容时()
,它会自动将括号放在整个表达式周围,就像
eval(expr(expr(`$`(mtcars,!!x))<=6))
做了,它只返回一个 FALSE。因此,如果这真的是我所期望的原因,我该如何让我filter()
知道我真正想要的是让它像这样评估:
eval(filter1<-expr(`$`(df,!!var2)))<=var2_upper
不是这个:
eval(filter1<-expr(`$`(df,!!var2))<=var2_upper)
如果我猜的不是怎么回事,也请帮助我。