38

次の式があるとしましょう。

myformula<-formula("depVar ~ Var1 + Var2")

式オブジェクトから従属変数名を確実に取得する方法は?

この目的に役立つ組み込み関数が見つかりませんでした。私はそれがas.character(myformula)[[2]]うまくいくことを知っています

sub("^(\\w*)\\s~\\s.*$","\\1",deparse(myform))

これらの方法は、信頼できる標準的な方法というよりも、ハッカーのように思えます。


たとえば、使用する方法を正確に知っている人はいlmますか?私はそれがコードであることを見てきましたが、それは私には少し不可解です...ここにあなたの便宜のための引用があります:

    > lm
function (formula, data, subset, weights, na.action, method = "qr", 
    model = TRUE, x = FALSE, y = FALSE, qr = TRUE, singular.ok = TRUE, 
    contrasts = NULL, offset, ...) 
{
    ret.x <- x
    ret.y <- y
    cl <- match.call()
    mf <- match.call(expand.dots = FALSE)
    m <- match(c("formula", "data", "subset", "weights", "na.action", 
        "offset"), names(mf), 0L)
    mf <- mf[c(1L, m)]
    mf$drop.unused.levels <- TRUE
    mf[[1L]] <- as.name("model.frame")
    mf <- eval(mf, parent.frame())
    if (method == "model.frame") 
        return(mf)
    else if (method != "qr") 
        warning(gettextf("method = '%s' is not supported. Using 'qr'", 
            method), domain = NA)
    mt <- attr(mf, "terms")
    y <- model.response(mf, "numeric")
    w <- as.vector(model.weights(mf))
    if (!is.null(w) && !is.numeric(w)) 
        stop("'weights' must be a numeric vector")
    offset <- as.vector(model.offset(mf))
    if (!is.null(offset)) {
        if (length(offset) != NROW(y)) 
            stop(gettextf("number of offsets is %d, should equal %d (number of observations)", 
                length(offset), NROW(y)), domain = NA)
    }
    if (is.empty.model(mt)) {
        x <- NULL
        z <- list(coefficients = if (is.matrix(y)) matrix(, 0, 
            3) else numeric(), residuals = y, fitted.values = 0 * 
            y, weights = w, rank = 0L, df.residual = if (!is.null(w)) sum(w != 
            0) else if (is.matrix(y)) nrow(y) else length(y))
        if (!is.null(offset)) {
            z$fitted.values <- offset
            z$residuals <- y - offset
        }
    }
    else {
        x <- model.matrix(mt, mf, contrasts)
        z <- if (is.null(w)) 
            lm.fit(x, y, offset = offset, singular.ok = singular.ok, 
                ...)
        else lm.wfit(x, y, w, offset = offset, singular.ok = singular.ok, 
            ...)
    }
    class(z) <- c(if (is.matrix(y)) "mlm", "lm")
    z$na.action <- attr(mf, "na.action")
    z$offset <- offset
    z$contrasts <- attr(x, "contrasts")
    z$xlevels <- .getXlevels(mt, mf)
    z$call <- cl
    z$terms <- mt
    if (model) 
        z$model <- mf
    if (ret.x) 
        z$x <- x
    if (ret.y) 
        z$y <- y
    if (!qr) 
        z$qr <- NULL
    z
}
4

7 に答える 7

41

使用してみてくださいall.vars

all.vars(myformula)[1]
于 2012-11-04T09:38:18.657 に答える
13

独自の関数をクックして使用することもできると思いますterms():

getResponse <- function(formula) {
    tt <- terms(formula)
    vars <- as.character(attr(tt, "variables"))[-1] ## [1] is the list call
    response <- attr(tt, "response") # index of response var
    vars[response] 
}

R> myformula <- formula("depVar ~ Var1 + Var2")
R> getResponse(myformula)
[1] "depVar"

と同じくらいハックas.character(myformyula)[[2]]ですが、呼び出し解析ツリーの順序がすぐに変更されることはないため、正しい変数を取得できるという保証があります。

これは、従属変数が複数ある場合にはあまり適していません。

R> myformula <- formula("depVar1 + depVar2 ~ Var1 + Var2")
R> getResponse(myformula)
[1] "depVar1 + depVar2"

さらなる処理が必要になるためです。

于 2012-11-04T10:03:00.540 に答える
6

名前だけでなく、実際の応答を取得するための編集に基づいて、lm()ベース R の式インターフェイスを備えた他のほとんどのモデリング関数で採用されている非標準の評価イディオムを使用できます。

form <- formula("depVar ~ Var1 + Var2")
dat <- data.frame(depVar = rnorm(10), Var1 = rnorm(10), Var2 = rnorm(10))

getResponse <- function(form, data) {
    mf <- match.call(expand.dots = FALSE)
    m <- match(c("formula", "data"), names(mf), 0L)
    mf <- mf[c(1L, m)]
    mf$drop.unused.levels <- TRUE
    mf[[1L]] <- as.name("model.frame")
    mf <- eval(mf, parent.frame())
    y <- model.response(mf, "numeric")
    y
} 

> getResponse(form, dat)
          1           2           3           4           5 
-0.02828573 -0.41157817  2.45489291  1.39035938 -0.31267835 
          6           7           8           9          10 
-0.39945771 -0.09141438  0.81826105  0.37448482 -0.55732976

ご覧のとおり、これは提供されたデータ フレームから実際の応答変数データを取得します。

...これがどのように機能するかは、式のデータの評価に必要のないものが含まれているため、引数を展開せずに関数が最初に関数呼び出しをキャプチャすることです。

次に、引数"formula""data"引数が呼び出しと一致します。この行mf[c(1L, m)]は、呼び出し ( 1L) から関数名を選択し、一致した 2 つの引数の場所を選択します。次の行でのdrop.unused.levels引数model.frame()が に設定さTRUEれ、呼び出しが更新されて、呼び出し内の関数名が から に切り替わりlmますmodel.frame。上記のコードが行うことはすべて、関数への呼び出しを受け取りlm()、関数への呼び出しを呼び出すプロセスですmodel.frame()

この変更された呼び出しは、関数の親環境 (この場合はグローバル環境) で評価されます。

最後の行は、model.response()extractor 関数を使用して、モデル フレームから応答変数を取得します。

于 2012-11-04T11:16:25.297 に答える
2

これにより、常にすべての依存変数が得られるはずです。

myformula<-formula("depVar1 + depVar2 ~ Var1 + Var2")
as.character(myformula[[2]])[-1]
#[1] "depVar1" "depVar2"

そして、私はこれを特に「ハッキー」とは考えていません。

編集:

3 つの依存関係で奇妙なことが起こります。

myformula<-formula("depVar1 + depVar2 + depVar3 ~ Var1 + Var2")
as.character(myformula[[2]])
#[1] "+"                 "depVar1 + depVar2" "depVar3" 

だから、これは私が思ったほど信頼できないかもしれません。

編集2:

さて、myformula[[2]]は言語オブジェクトであり、as.characterと似たようなことをしているようlanguageElです。

length(myformula[[2]])
#[1] 3
languageEl(myformula[[2]],which=1)
#`+`
languageEl(myformula[[2]],which=2)
#depVar1 + depVar2
languageEl(myformula[[2]],which=3)
#depVar3
languageEl(languageEl(myformula[[2]],which=2),which=2)
#depVar1

各要素の長さを確認すると、独自の抽出関数を作成できます。しかし、これはおそらくハックしすぎです。

Edit3: @seancarmody による回答に基づいて、all.vars(myformula[[2]])進むべき道です。

于 2012-11-04T09:54:13.583 に答える