eval(parse())、eval(str2lang())、eval(str2expression())和eval(call()[[1]])之间有什么区别?
我正在编写一个函数,从给定的data.frameeval(parse())、eval(str2lang())、eval(str2expression())和eval(call()[[1]])之间有什么区别?,r,eval,R,Eval,我正在编写一个函数,从给定的data.framedf或环境env中提取作为字符串提供的变量。最初,我一直在使用eval(parse(text=s)、df、env)构造来实现这一点,但我知道还有更有效的替代方法。其他选择包括: eval(str2lang(s)、df、env) eval(str2表达式、df、env) eval(呼叫[[1]],df,env) 可能还有一个get解决方案,但我不知道它是否可以先检查变量是否在df中,然后再转到env,如果不是 使用microbenchmark,似乎c
df
或环境env
中提取作为字符串提供的变量。最初,我一直在使用eval(parse(text=s)、df、env)
构造来实现这一点,但我知道还有更有效的替代方法。其他选择包括:
eval(str2lang(s)、df、env)
eval(str2表达式、df、env)
eval(呼叫[[1]],df,env)
get
解决方案,但我不知道它是否可以先检查变量是否在df
中,然后再转到env
,如果不是
使用microbenchmark
,似乎call
是最快的:
库(微基准)
x1=1
df=数据帧(x2=2)
微基准(call=eval(call('x1')[[1]],df),
parse=eval(parse(text='x1'),df),
str2lang=eval(str2lang('x1'),df),
str2exp=eval(str2表达式('x1'),df),
check=“等同”)
#>单位:微秒
#>expr最小lq平均uq最大neval cld
#>致电1.128 1.21151.60815 1.4585 1.6360 4.659 100 a
#>解析39.183 39.8705 46.60755 40.2405 42.0415 135.462 100 b
#>str2lang 2.235 2.3570 3.26144 2.5995 2.8925 24.641 100 a
#>str2exp 2.230 2.3200 2.81387 2.4780 2.6970 10.312 100 a
微基准(call=eval(call('x2')[[1]],df),
parse=eval(parse(text='x2'),df),
str2lang=eval(str2lang('x2'),df),
str2exp=eval(str2表达式('x2'),df),
check=“等同”)
#>单位:微秒
#>expr最小lq平均uq最大neval cld
#>致电1.124 1.194 1.47770 1.3675 1.5795 9.031 100 a
#>解析38.254 38.762 40.21497 38.9630 39.3120 116.510 100 b
#>str2lang 2.214 2.304 2.55036 2.3960 2.6530 10.639 100 a
#>str2exp 2.238 2.331 2.50011 2.4210 2.6515 3.619 100 a
由(v0.3.0)于2020年4月23日创建
因此,我倾向于使用
call
,但我希望确保这样做不会产生任何意外后果,而不是使用其他解决方案。换句话说,在什么情况下(在我使用它们的上下文中),这四种方法不会给出相同的答案,导致一种方法优于其他方法?我认为这取决于您尝试评估的字符串。如果它总是一个单一的名称,那么as.name('x1')
可能也是一个竞争者;我的测试表明,它比您使用调用的解决方案稍微慢一点,但我认为它更可取,因为它不那么晦涩,也不太可能引起未来的麻烦
这可能会引起麻烦:当前call(“x1”)
生成语言对象x1()
,然后提取被调用函数的名称。但是,如果在R的未来版本中,它记住该表达式中的x1
应该是一个函数呢eval(x1())
已经知道忽略名为x1
的非函数对象,因此它不会破坏太多代码来进行更改,从效率的角度来看,它可能很有用
as.name
还允许非字符参数,例如as.name(123)
;这对你来说可能是积极的,也可能是消极的。(两种解决方案都允许“123”
)我认为这取决于您试图计算的字符串。如果它总是一个单一的名称,那么as.name('x1')
可能也是一个竞争者;我的测试表明,它比您使用调用的解决方案稍微慢一点,但我认为它更可取,因为它不那么晦涩,也不太可能引起未来的麻烦
这可能会引起麻烦:当前call(“x1”)
生成语言对象x1()
,然后提取被调用函数的名称。但是,如果在R的未来版本中,它记住该表达式中的x1
应该是一个函数呢eval(x1())
已经知道忽略名为x1
的非函数对象,因此它不会破坏太多代码来进行更改,从效率的角度来看,它可能很有用
as.name
还允许非字符参数,例如as.name(123)
;这对你来说可能是积极的,也可能是消极的。(两种解决方案都允许“123”
)