gpt4 book ai didi

r - 如何引用函数中的列

转载 作者:行者123 更新时间:2023-12-02 16:21:08 26 4
gpt4 key购买 nike

我试图编写一个包含两个操作的函数,第一个操作包括对数据帧进行子集化。

假设我有这两个数据框。

      ID   Var1
1 5 3
2 6 1



ID Var2
1 5 9
2 6 2

而我的功能是这样的

mu_fuc = function(df, condition) {
workingdf = subset(df, condition < 3)

###pass working df to the other action
}

我知道对于第一个操作,我可以使用条件切片作为变通方法。但是,当我尝试处理其他操作时,我意识到我仍然必须为另一个现有函数引用数据框中的列名。

我尝试了 as.name(condition),但没有成功。

感谢您的宝贵时间。非常感谢任何建议。

--------12月26日更新------------

使用 eval 的方法对函数一次效果很好,如下所示。

meta = function(sub_data, y) {
y <- eval(as.list(match.call())$y, sub_data)
workingdf <- subset(sub_data, y != 999) ##this successfully grab the column named y in the dataframe##

meta1 <- metacor(y, ##this successfully grab the column named y in the dataframe##
n,
data = workingdf,
studlab = workingdf$Author_year,
sm = "ZCOR",
method.tau = "SJ",
comb.fixed = F)
return(meta1)

但不知何故,相同的方法在以下代码中不起作用。

mod_analysis = function(meta, moderator){
workingdf <- meta$data
moderator <- eval(as.list(match.call())$moderator, workingdf)

output = metareg(meta, moderator)
return(output)
}

然后是这个错误信息:

Error in eval(predvars, data, env) : object 'moderator' not found 

我不知道为什么它对第一个功能有效但对第二个功能无效。

最佳答案

可以转换 condition从简单的列引用到表达式,使函数参数能够包含表达式的右侧,而不是将其硬编码到函数中。这可以通过 rlang 中的几个函数来完成。包,enquo()eval_tidy() .

我们将使用子集函数和 mtcars 来说明这一点数据框。

aSubsetFunction <- function(df,condition){
require(rlang)
condition <- enquo(condition)
rows_value <- eval_tidy(condition, df)
stopifnot(is.logical(rows_value))
df[rows_value, ,drop = FALSE]
}

condition <- enquo(condition)行引用条件表达式。 eval_tidy()函数计算引用的表达式,使用 df作为数据掩码。 eval_tidy() 的输出, rows_value , 是逻辑值向量 (TRUE/FALSE),我们在输入数据框的行维度上使用 [提取运算符的形式。我们使用 stopifnot()如果 rows_value 则生成错误不是逻辑值的向量。

我们调用该函数两次以说明它适用于数据框中的多列。

aSubsetFunction(mtcars,mpg > 25)
aSubsetFunction(mtcars,carb > 4)

...和输出:

> aSubsetFunction(mtcars,mpg > 25)
Loading required package: rlang
mpg cyl disp hp drat wt qsec vs am gear carb
Fiat 128 32.4 4 78.7 66 4.08 2.200 19.47 1 1 4 1
Honda Civic 30.4 4 75.7 52 4.93 1.615 18.52 1 1 4 2
Toyota Corolla 33.9 4 71.1 65 4.22 1.835 19.90 1 1 4 1
Fiat X1-9 27.3 4 79.0 66 4.08 1.935 18.90 1 1 4 1
Porsche 914-2 26.0 4 120.3 91 4.43 2.140 16.70 0 1 5 2
Lotus Europa 30.4 4 95.1 113 3.77 1.513 16.90 1 1 5 2
> aSubsetFunction(mtcars,carb > 4)
mpg cyl disp hp drat wt qsec vs am gear carb
Ferrari Dino 19.7 6 145 175 3.62 2.77 15.5 0 1 5 6
Maserati Bora 15.0 8 301 335 3.54 3.57 14.6 0 1 5 8

使用原始帖子中的数据,解决方案的工作原理如下。

df1 <- read.csv(text="ID,Val1
5,3
6,1")
df2 <- read.csv(text="ID,Val2
5,9
6,2")
aSubsetFunction(df1,Val1 < 3)
aSubsetFunction(df2,Val2 < 3)

...和输出:

> aSubsetFunction(df1,Val1 < 3)
ID Val1
2 6 1
> aSubsetFunction(df2,Val2 < 3)
ID Val2
2 6 2

说明了方法后,我们可以使用 R 中的对象求值顺序将函数简化为一行 R 代码:

aSubsetFunction <- function(df,condition){
require(rlang)
df[eval_tidy(enquo(condition), df), ,drop = FALSE]
}

...产生与上面所列相同的输出。

> aSubsetFunction(mtcars,mpg > 25)
Loading required package: rlang
mpg cyl disp hp drat wt qsec vs am gear carb
Fiat 128 32.4 4 78.7 66 4.08 2.200 19.47 1 1 4 1
Honda Civic 30.4 4 75.7 52 4.93 1.615 18.52 1 1 4 2
Toyota Corolla 33.9 4 71.1 65 4.22 1.835 19.90 1 1 4 1
Fiat X1-9 27.3 4 79.0 66 4.08 1.935 18.90 1 1 4 1
Porsche 914-2 26.0 4 120.3 91 4.43 2.140 16.70 0 1 5 2
Lotus Europa 30.4 4 95.1 113 3.77 1.513 16.90 1 1 5 2
> aSubsetFunction(mtcars,carb > 4)
mpg cyl disp hp drat wt qsec vs am gear carb
Ferrari Dino 19.7 6 145 175 3.62 2.77 15.5 0 1 5 6
Maserati Bora 15.0 8 301 335 3.54 3.57 14.6 0 1 5 8
>

结语:为什么我们不能使用 subset() 进行变量替换?

从最初看问题时,人们可能认为我们可以使用以下代码解决问题。

subset2 <- function(df,condition){
subset(df,df[[condition]] > 4)
}

subset2(mtcars,carb)

但是,这会失败并出现未找到对象错误:

 Error in (function(x, i, exact) if (is.matrix(i)) as.matrix(x)[[i]] else .subset2(x,  : 
object 'carb' not found

再次Advanced R提供解释,直接引用 subset() 的文档.

This is a convenience function intended for use interactively. For programming it is better to use the standard subsetting functions like [, and in particular the non-standard evaluation of argument subset can have unanticipated consequences.

底线:在编写函数以自动执行分析时,了解 Base R 非标准评估非常重要,因为编码到各种 R 函数中的假设可能会产生意想不到的结果。对于像 lm() 这样的建模函数尤其如此。依赖formula() ,正如 Wickham 在 Advanced R: wrapping modeling functions 中描述的那样.

引用文献:Advanced R, Chapter 20 section 4 , Chapter 20 section 6

关于r - 如何引用函数中的列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65449428/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com