2015-04-22 18 views
5

我想編寫一個函數,用於評估數據框中的表達式,但使用可能包含或不包含用戶定義的表達式的表達式,定義的對象。 我覺得這個魔法詞是「非標準評估」,但我還不能完全弄明白。R:使用作爲對象傳遞的參數來評估數據框中的表達式

一個簡單的例子(對於我的目的來說是現實的):說,我想評估一個lm()調用在數據框中找到的變量。

mydf <- data.frame(x=1:10, y=1:10) 

,它因此可以寫成一個函數如下:

f <- function(df, expr){ 
    expr <- substitute(expr) 
    pf <- parent.frame() 
    eval(expr, df, pf) 
} 

這樣的,我得到了我想要使用下面的命令是什麼。

f(mydf, lm(y~x)) 

# Call: 
# lm(formula = y ~ x) 
# 
# Coefficients: 
# (Intercept)   x 
# 1.12e-15  1.00e+00 

不錯。但是,有些情況下,在調用lm()之前將模型方程保存在對象中更方便。不幸的是,上述功能不再適用。

fml <- y~x 

f(mydf, lm(fml)) 
# Error in eval(expr, envir, enclos): object 'y' not found 

有人可以解釋爲什麼第二個電話不起作用嗎?這個函數怎麼可能被改變,這樣兩個調用都會導致期望的結果? (希望=適合型號)

乾杯!

回答

4

?lm,重新data說法:

如果數據未找到,變量從環境中獲取(公式)

在你的第一種情況下,該公式是在eval(expr, df, pf)創建呼叫,所以公式的環境是基於df的環境。在第二種情況下,公式是在全球環境中創建的,這就是爲什麼它不起作用。

因爲公式帶有自己的環境,所以在NSE中處理它們可能會非常棘手。

你可以嘗試:

with(mydf, 
    { 
    print(lm(y~x)) 
    fml <- y~x 
    print(lm(fml)) 
    } 
) 

但這可能不是您理想的選擇。檢查捕獲的參數中的任何名稱是否解析爲公式並重新分配其環境,都會遇到一些麻煩。 更糟糕的是,重新分配環境並不一定是顯而易見的。在許多情況下,你確實想看看公式環境。

有R上聊天在這一問題上鬆散的相關討論:

+0

我想我明白你的意思,雖然我也詞組它有點不同。讓我看看我是否明白這一點:問題在於'eval()'必須在'lm()'可以作爲一個整體進行評估之前查找對象'fml'。由於'fml'在數據框中不可用,'eval'可以通過'pf'找到它。該公式是在那裏找到的,因爲它是在那裏創建的,但不會看到「y」或「x」。 – SimonG

+1

@SimonG問題不在於'eval'。問題在於'lm'在'environment'(公式)'中查找變量,而不考慮lm'調用的評估幀。 – BrodieG