Я пытаюсь написать функцию, которая принимает два имени столбца и верхнюю и / или нижнюю границу для каждого имени столбца, чтобы таким образом я мог подгруппировать данные с именами столбцов и границей по своему выбору. Используя mtcars в качестве примера, если я хочу подмножество данных, говоря, что я хочу только строки с cyl> 4 и mpg> 15, в этом случае моя функция будет принимать два имени столбца cyl и mpg, а также две нижние границы для каждого столбцаname - это 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)
Я получаю 0 счетчиков и NaN для avgcrl в final1. Поэтому, когда filter()
оценивает, что внутри ()
, он получает только ЛОЖЬ, не ИСТИНА, я думаю, поэтому строки не возвращаются.
У меня есть теория, почему это происходит. Если я сделаю это:
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)
Если я догадался не о том, что происходит, пожалуйста, помогите мне.