R系列之在逻辑判断中传递变量

这篇文章记录了在R中的逻辑判断式中添加参数的方法,主要有两种,一种是substitute结合eval,另一种是parse结合eval,两种方法都是先得到unevaluated expressions,而后使用eval对得到的表达式进行求值。

背景

最近想在函数中添加一个subset命令来获取不同的数据,但是发现函数中传递的参数不能直接用到逻辑判断式中。


问题

1
2
3
4
5
6
7
8
9
10
11
12
raw_data<- data.frame(Blok=c(1,2,3,0))
raw_data
Blok
1 1
2 2
3 3
4 0

# 得到其中Blok大于1的行
Blok
2 2
3 3

解决方法

substitute结合eval

substitute函数作用:

substitute returns the parse tree for the (unevaluated) expression expr, substituting any variables bound in env.

其实substitute就是用来构建一个单纯的表达式,这个表达式并没有进行求值,具体求值是eval函数的作用。

1
2
3
4
5
6
7
8
9
10
11
12
13
# list中给出的是前面exp中需要替换的部分
# 可以发现输出的只是这个单纯的表达式,并没有对其进行求值
substitute(x <- x + 1, list(x = 1))
1 <- 1 + 1

# 对这个表达式进行求值
1 <- 1 + 1
Error in 1 <- 1 + 1 : invalid (do_set) left-hand side to assignment

# 使用eval函数
# 发现eval其实就是相当于指定了得到的表达式
eval(substitute(x <- x + 1, list(x = 1)))
Error in 1 <- 1 + 1 : invalid (do_set) left-hand side to assignment

回归到前面的问题上:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
subset(raw_data,eval(substitute(x > 1, list(x = as.name("Blok")))))
Blok
2 2
3 3

# 注意这里as.name的用法
# 得到的是Blok而不是字符串"Blok"
# subset中可以直接传入前面data的列名即可
as.name("Blok")
Blok
"Blok"
[1] "Blok"

subset(raw_data,Blok>1)
Blok
2 2
3 3
subset(raw_data,"Blok">1)
Blok
1 1
2 2
3 3
4 0

关于as.name:

A ‘name’ (also known as a ‘symbol’) is a way to refer to R objects by name (rather than the value of the object, if any, bound to that name).


parse结合eval

parse函数功能:

parse returns the parsed but unevaluated expressions in a list.

其功能和前面的substitute类似,都是返回unevaluated expressions

针对前面的问题:

1
2
3
4
5
6
7
keep_rows <- "Blok>1"
parse(text=keep_rows)
expression(Blok>1)
subset(raw_data,eval(parse(text=keep_rows)))
Blok
2 2
3 3


参考链接



-----本文结束感谢您的阅读-----

本文标题:R系列之在逻辑判断中传递变量

文章作者:showteeth

发布时间:2020年05月08日 - 22:29

最后更新:2020年05月21日 - 23:15

原始链接:http://showteeth.tech/posts/5754.html

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

0%