2017-07-29 41 views
0

R代碼裏面如何編寫一個R函數來確保我們得到一個變量但不是col的data.table?

library(data.table) 
x <- 4 
f1 <- function(){ 
    x <- 1 
    dt <- data.table(x=1:4,y=1:12) 
    dt[x==get("x", envir=parent.env(environment()))] 
} 
f1() 

我得到這個:

x y 
1: 1 1 
2: 1 5 
3: 1 9 

f2是一個新的功能,在功能刪除x <- 1

f2 <- function(){ 
    #x <- 1 
    dt <- data.table(x=1:4,y=1:12) 
    dt[x==get("x", envir=parent.env(environment()))] 
} 
f2() 

我得到這個:

x y 
1: 4 4 
2: 4 8 
3: 4 12 

這是正確的,我的問題是如何編寫一個函數來代替get("x", envir=parent.env(environment()))

謝謝!

回答

1

我只是意識到OP從函數的封閉環境中抓取x而不是將它作爲參數傳遞。我認爲這種不好的做法,並沒有真正的建議。如果太多分心,我可能會刪除這個答案(只包括傳遞給函數x)。

library(data.table) 
dt <- data.table(x=1:4,y=1:12) 

ff = function(x, ...){ 
    mDT = data.table(x) 
    dt[mDT, on=.(x), ...] 
} 

ff(4L, verbose = TRUE) 

# Calculated ad hoc index in 0 secs 
# Starting bmerge ...done in 0 secs 
# x y 
# 1: 4 4 
# 2: 4 8 
# 3: 4 12 

這隻能滿足業務方案的具體例子中,DT[x == get("x", ...)],而不是更廣泛的表達。對於那些,構建和評估表達式應該工作:

fs = function(x, ...){ 
    e = substitute(x == ..x, list(..x = x)) 
    dt[eval(e), ...] 
} 

fs(4L, verbose = TRUE) 

# Creating new index 'x' 
# Starting bmerge ...done in 0 secs 
# x y 
# 1: 4 4 
# 2: 4 8 
# 3: 4 12 

fs(3L, verbose = TRUE) 

# Using existing index 'x' 
# Starting bmerge ...done in 0 secs 
# x y 
# 1: 3 3 
# 2: 3 7 
# 3: 3 11 

詳細輸出指示fs創建索引,其可以是對速度有幫助的。見vignette("datatable-secondary-indices-and-auto-indexing")


Eventually,有可能是語法,所以我們可以簡單地寫......

dt[..x == x] 

可能使用來自鏈接安全所提出的論點inherits = TRUE(這樣x必須是列,要麼( i)x必須存在於父環境中或..x必須是列名稱)。

+0

我以爲'..x'語法不是一個好主意,因爲'..x'可以是一個合法變量。我們可能無法理解「...... a」或「... a」的含義。 – liqg3

+0

@ liqg3是的,這是一個很好的觀點。如果/當'inherits = TRUE'是一個選項,那麼唯一的要求就是'..x'不是一個列名(所以它會搜索「上一層」爲'x'),我想。你的編輯到你的問題應該/可以作爲一個答案在這裏發佈。 – Frank

+1

感謝您的回答,這是我第一次看到data.table的輔助鍵,這對於大數據操作非常有幫助。 – liqg3

1

@Frank,謝謝!基於這個帖子variable usage in data.table,我寫了一個函數:

`..` <- function(x){ 
    stopifnot(inherits(x, "character")) 
    stopifnot(length(x)==1) 
    get(x, parent.frame(4)) 
} 
x <- 4 
f1 <- function(){ 
    x <- 1 
    dt <- data.table(x=1:4,y=1:12) 
    dt[x==..("x")] 
} 
f1() 

f2 <- function(){ 
    #x <- 1 
    dt <- data.table(x=1:4,y=1:12) 
    dt[x==..("x")] 
} 
f2() 

F1和F2得到正確的結果!

爲什麼parent.frame(4)?

我們看到代碼第一:

current_frame <- sys.nframe() 
dt <- data.table() 
dt[, sys.nframe() - current_frame] 

我們得到了4,這應該是這個原因。

相關問題