2017-05-30 33 views
2

目標是能夠使用「子集表達式」(不是邏輯向量)作爲用戶定義函數的(可選)參數並使用它來計算數據幀的子集。使子集()在函數中工作

x <- data.frame(a=1, b=gl(2,5)) 

f <- function(data, subset) { 
    if (!missing(subset)) 
     data <- subset(data, subset) 
    data 
} 

上面的代碼無法正常工作,而且也不

f <- function(data, subset) { 
    if (!missing(subset)) 
     data <- data[with(data, subset), ] 
    data 
} 

在這兩種情況下,當供給subset我得到一個錯誤。

> f(x, b == 2) 
Error in f(x, b == 2) (from frame.r!322341dM#2) : object 'b' not found 

所需的輸出:

> f(x) 
    a b 
1 1 1 
2 1 1 
3 1 1 
4 1 1 
5 1 1 
6 1 2 
7 1 2 
8 1 2 
9 1 2 
10 1 2 
> f(x, b == 2) 
    a b 
6 1 2 
7 1 2 
8 1 2 
9 1 2 
10 1 2 
+0

您需要'x $ b == 2'。 – G5W

+0

b不是變量,它是x中的一列,所以您需要它以R理解的方式輸入函數(或者粘貼到函數中)。它可以如G5W所說,或者你可以設置函數來獲取三個屬性,數據框,列名和值,然後將它們粘貼在函數中以提取所需的輸出。 – sconfluentus

回答

4

這一次似乎工作。你必須告訴f即第二arg是一個表達式:

f <- function(data, ss) { 
    if (!missing(ss)){ 
     e <- substitute(ss) 
     r <- eval(e, data, parent.frame()) 
     data <- subset(data, r) 
    } 
    data 
} 

# > f(x, b == 2) 
# a b 
# 6 1 2 
# 7 1 2 
# 8 1 2 
# 9 1 2 
# 10 1 2 

subset替換參數名ss將無法​​正常工作。我不知道爲什麼。其實,我通過瀏覽subset.data.frame的源代碼想出了。

+0

@ G.Grothendieck,編輯。我在「子集」的源代碼中看到了這一點,但不確定它的作用。感謝您解釋這一點。 – mt1022

1

由於您的功能基本上與subset()具有相同的簽名,您也可以直接將參數直接傳遞給subset()

f <- function(data, ss) { 
    if (!missing(ss)){ 
     call <- unname(match.call()) 
     call[[1]] <- quote(subset) 
     data <- eval(call, parent.frame()) 
    } 
    data 
} 

unname()是必要的,因爲在這裏你比subset()功能給這個函數不同的參數名。但基本上,我們只需撥打subset()即可將呼叫轉接至您的功能。這意味着我們不必在適當的環境下評估過濾器的「骯髒工作」。