簡體   English   中英

(Pre)為工廠和內部提供變量

[英](Pre)supply variables to function factory and within

我正在閱讀哈德利的高級R並嘗試一些東西。 我試圖創建一個lazy ,與所提供的返回功能閉合功能data.frame在其環境以及使用with和能夠后來提供額外的功能參數。

lazy <- function(dataframe, x) {
    function(FUN, x, ...) {
        with(dataframe, FUN(x = x, ...))
    }
}

lz_factory <- lazy(mtcars, "mpg")

lz_factory(mean)
lz_factory(cor, y="hp")

所以我期待數據幀是功能環境的一部分( browser看起來確認)。 但是,變量名x不供應,當我使用cor作為第一個FUN參數時,我無法提供新變量y 這與為使用非標准評估(NSE)的函數( with )提供字符有關。 我希望哈德利叔叔為我感到驕傲,但我用evalparsesubstitute所有返回的錯誤。 這意味着我不完全了解R如何處理事情。 我知道為什么它不起作用(NSE)但不知道如何使其工作。 這是錯誤:

> lz_factory(mean)
Error in FUN(x = x, ...) : argument "x" is missing, with no default

> lz_factory(cor, y="hp")
Error in is.data.frame(x) : argument "x" is missing, with no default

我想我可以使用替補來解決它,因為Hadley在這里用xyplot顯示,但這也是一個失敗,如下所示:

lazy <- function(dataframe, default) {
    function(FUN, x, ...) {
        if (missing(x)) x <- default
        eval(substitute(with(dataframe, FUN(x, ...))))
    }
}

lz_factory <- lazy(mtcars, "mpg")

lz_factory(mean)
lz_factory(cor, y="hp")


> lz_factory(mean)
[1] NA
Warning message:
In mean.default("mpg") : argument is not numeric or logical: returning NA

> lz_factory(cor, y="hp")
Error in cor("mpg", y = "hp") : 'x' must be numeric

那么我怎樣才能使這個惰性函數工作呢:

  1. 使用環境中包含的數據框生成自己的函數
  2. 如果需要,允許我提供x,如果不使用,則允許我使用最初提供的默認值
  3. 允許我將未知變量傳遞給lz_factory創建的lz_factory

最好我想讓這個功能與之with 如果那是不可能的,那么知道為什么會很好。 最后一點,如果無法使用with我怎樣才能使功能操作?

這是@ MrFlick函數的略微簡化版本:

lazy <- function(df, x_var = NULL) {
  x <- substitute(x_var)

  function(FUN, ...) {
    call <- substitute(FUN(...))
    if (is.null(call$x) && !is.null(x)) {
      call$x <- x
    }
    eval(call, df, parent.frame())
  }
}

關鍵是更好地利用substitute()的功能,並通過直接使用eval避免with()

這個功能怎么樣

lazy <- function(dataframe, ...) {
    pdots <- substitute(list(...))
    if(is.null(names(pdots)) || names(pdots)[1]=="") {
        names(pdots)[2]<-"x"
    }
    function(FUN, ...) {
        dots <- substitute(list(...))[-1]
        if (is.null(dots$x)) {
            dots$x <- pdots$x
        }
        with(dataframe, do.call(FUN, as.list(dots)))
    }
}

這允許您在沒有引號的mtcars中使用變量的名稱。 例如

lz_factory <- lazy(mtcars, mpg)
lz_factory(mean)
# [1] 20.09062
lz_factory(mean, x=hp)
# [1] 146.6875
lz_factory(cor, y=hp)
# [1] -0.7761684

在這里,我們使用額外的替換來確保我們得到延遲評估並允許您使用不帶引號的變量名稱。 with將負責評估表達式。 我猜可能有辦法簡化這個,但至少它似乎有效。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM