2016-06-15 42 views
1

我希望能夠將一串過濾條件傳遞給data.table。我試着解析和eval的所有舉止,似乎無法弄清楚如何評估一個字符串以過濾R data.table?

我嘗試使用虹膜數據集來重建一個例子:

iris <- data.table(iris) 

vars <- 'setosa'      
filter <- 'Species == vars & Petal.Length >= 4' 

data <- iris[filter, list(
          sep.len.tot = sum(Sepal.Length) 
         , sep.width.total = sum(Sepal.Width) 
      ), by = 'Species'] 

所以過濾串有一個變量變量(基於循環變化)。我試圖根據過濾器字符串過濾數據。

是否有一個data.table評估字符串的特定方法?

希望有道理!

回答

3

我認爲eval(parse(text()))會工作,你只需要一些修改。試試這個:

library(data.table) 
iris <- data.table(iris) 

#Updated so it will have quotes in your string 
vars <- '\"setosa\"' 
#Update so you can change your vars 
filter <- paste0('Species==',vars,'& Petal.Length >= 4') 

res <- iris[eval(parse(text=filter)), list(
    sep.len.tot = sum(Sepal.Length) 
    , sep.width.total = sum(Sepal.Width) 
), by = 'Species'] 

的幾個注意事項:我更新了vars字符串中這樣就會有行情,以便正常運行,我也更新filter這樣你就可以動態地改變0​​。

最後,爲了便於說明,得到的DF是空白(因爲沒有setosa品種有Petal.Length> = 4。因此,爲了看到這項工作,我們就可以去掉最後一個條件。

filter <- paste0('Species==',vars) 
res2 <- iris[eval(parse(text=filter)), list(
    sep.len.tot = sum(Sepal.Length) 
    , sep.width.total = sum(Sepal.Width) 
), by = 'Species'] 

res2 
    Species sep.len.tot sep.width.total 
1: setosa  250.3   171.4 

編輯: 每@下面弗蘭克的評論,更清潔的方法是編寫整個事情作爲表達式:

filter <- substitute(Species == vars, list(vars = "setosa")) 

res <- iris[eval(filter), list(
    sep.len.tot = sum(Sepal.Length) 
    , sep.width.total = sum(Sepal.Width) 
), by = 'Species'] 
+0

啊,使一個很大的意義!非常感謝! – AlexP

+2

我想在表達式中替換是比較乾淨的,而不是粘貼和解析。我的意思是'filter < - substitute(Species == vars&Petal.Length> = 4,list(vars =「setosa」));虹膜[eval(filter)]' – Frank

+1

哦,哇,不知道你能做到這一點。我會編輯我的答案,謝謝@Frank! –

0

您需要粘貼您的過濾器,並添加引號,即filter <- paste0('Species==\'',vars,'\' & Petal.Length >= 4')

然後你可以使用

eval(parse(text=paste0('iris[',filter,',list(sep.len.tot = sum(Sepal.Length), sep.width.total = sum(Sepal.Width)), by = \'Species\']'))) 
+0

如果這給你一個空表,這是因爲沒有setosas,在數據中petal.length> = 4。 – jkt