2017-09-11 41 views
0

我想在我的數據上使用dplyr的新NSE符號(版本> = 0.6)作爲動態filter。比方說,我有以下的虛擬數據集:dplyr中基於字符串的過濾-NSE

df = data_frame(x = 1:10, y = 10:1, z = 10 * runif(10)) 

如果現在我要當數值大於5,我知道更大的過濾列tofilter = "x"我可以這樣做:

df %>% 
    filter((!!rlang::sym(tofilter)) >= 5) 

問題1

如果我想動態更改過濾器的操作符(假設我有一個Shiny應用程序,用戶可以動態地使用selectInput如果要過濾大於5,等於5或更低的值的數據一個5?

我希望做的是對的東西行:

op = ">=" 
val = 5 
filt_expr = paste("x", op, val) 
df %>% 
    filter(filt_expr) 

顯然,這不工作,我打了一下與rlang quosore /符號等,但也不太找到正確的方式來「引用」我的投入。

問題2

獎金的問題是,如果我想申請多個過濾器是什麼?我是否需要循環或者我可以創建一個過濾表達式列表並一次性應用它們?

這方面的一個例子是一個閃亮的應用程序,用戶可以鍵入他/她想要應用到數據,使我們有格式的動態變化列表中的多個條件:

filt_expr_list = list("x >= 5", "y <= 10", "z >= 2") 

,我們希望動態地應用它們,從而使輸出等同於:

df %>% 
    filter(x >= 5, y <= 10, z >= 2) 

我想這是在一定的意義,因爲當我知道如何正確地引用我想我可以做一些參數問題1的子集如:

filt_expr = paste0(unlist(filt_expr_list), collapse = ", ") 
df %>% 
    filter(filt_expr) 

,但會很高興地看到,如果有任何更好的更清潔的方式

回答

3

如果我想動態改變過濾的操作太

你可以用整齊這麼做通過不加引號表示運算符的符號(注意,我使用expr()來說明不加引號的結果):

lhs <- "foo" 

# Storing the symbol `<` in `op` 
op <- quote(`<`) 

expr(UQ(op)(!! sym(lhs), 5)) 

此輸出foo < 5

然而,使用普通的R代碼在整潔評估之外做得更乾淨。只有當您取消引用的符號表示數據框中的列時,即不在上下文中的情況下,才需要取消引用。在這裏你可以存儲操作員一個變量,然後調用該變量在你的過濾表達式:

# Storing the function `<` in `op` 
op <- `<` 
expr(op(!! sym(lhs), 5)) 

此輸出op(foo, 5)

如果我想應用多個過濾器,該怎麼辦?

您保存到列表中的表達式,然後你拼接他們在通話中與!!!

filters <- list(
    quote(x >= 5), 
    quote(y <= 10), 
    quote(z >= 2) 
) 

expr(df %>% filter(!!! filters)) 

此輸出df %>% filter(x >= 5, y <= 10, z >= 2)

注意:我上面說,這是沒有必要的從上下文中取消引用變量,但如果您正在編寫以數據框爲輸入的函數,那麼這樣做通常是個好主意。由於數據框架是可變的,所以您事先不知道它包含哪些列。這些列始終優先於您在環境中定義的對象。在這裏,這不是問題,因爲我們正在討論一個函數,如果R在數據框中找到一個類似命名的對象,它將繼續尋找一個函數。

+0

你是完全正確的!偉大的解決方案,謝謝你!總結一下,可以運行多個動態過濾器來創建一個類似'filt_expr = list( quo(\'> = \'(!! sym(「x」),5)), quo(\ = \'(!! sym(「y」),10)), quo(\'> = \'(!! sym(「z」),2)) )'然後應用'!!! 'operator'df%>% filter(!!! filt_expr)'。 –