2017-10-08 3 views
2

数式を代用する方法については、answerを受け取ったことがあります。私はdata.framesのリストを一致させるために必要です。MatchItで認識されない置換された式を扱うにはどうすればよいですか?

MatchIt::matchit()と一致させる場合、最初に結果をmatchit.full/matchitクラスとして保存する必要があります。次に、match.data() data.framesで、一致した観測のみが作成されます。

問題は、いつものように式を使用すると問題なく動作しています。代用の場合は、match.data()は何とか式を認識する必要があるようですが、そうではありません。置換がエラーError in eval(object$call$data, envir = env) : object 'mark' not foundを生成/ W/O置換が正常に動作している、試行W試みを見ることができるように

# example list 
library(car) 
WeightLoss1 <- WeightLoss 
WeightLoss1$group <- as.integer(ifelse(WeightLoss1$group == "Control", 0, 1)) 

WL = list(WeightLoss1, WeightLoss1, WeightLoss1) # doesn't make much sense, but suffices for example 

# substitute formula 
wl.cov <- c("wl1", "se1") 
WL.FM <- reformulate(wl.cov, response = "group") 

# matching w/o substitution 
m.match.0 <- lapply(1:length(WL), function(mark) { 
    require(MatchIt) 
    matchit(group ~ wl1 + se1, data = WL[[mark]]) 
}) 

# matching w/ substitution 
m.match.1 <- lapply(1:length(WL), function(mark) { 
    require(MatchIt) 
    matchit(WL.FM, data = WL[[mark]]) 
}) 

# now compare both attempts to create list of data.frames 
# w/o 
match <- lapply(1:length(m.match.0), function(i){ 
    require(MatchIt) 
    match.data(m.match.0[[i]]) 
}) 

# w/ 
match <- lapply(1:length(m.match.1), function(i){ 
    require(MatchIt) 
    match.data(m.match.1[[i]]) 
}) 

は、例えば(警告は無視することができる)としてこれを考慮してください。

これはどのように修正できますか?

-

ノート

> match.data 
function (object, group = "all", distance = "distance", weights = "weights", 
    subclass = "subclass") 
{ 
    if (!is.null(object$model)) { 
     env <- attributes(terms(object$model))$.Environment 
    } 
    else { 
     env <- parent.frame() 
    } 
    data <- eval(object$call$data, envir = env) 
    treat <- object$treat 
    wt <- object$weights 
    vars <- names(data) 
    if (distance %in% vars) 
     stop("invalid input for distance. choose a different name.") 
    else if (!is.null(object$distance)) { 
     dta <- data.frame(cbind(data, object$distance)) 
     names(dta) <- c(names(data), distance) 
     data <- dta 
    } 
    if (weights %in% vars) 
     stop("invalid input for weights. choose a different name.") 
    else if (!is.null(object$weights)) { 
     dta <- data.frame(cbind(data, object$weights)) 
     names(dta) <- c(names(data), weights) 
     data <- dta 
    } 
    if (subclass %in% vars) 
     stop("invalid input for subclass. choose a different name.") 
    else if (!is.null(object$subclass)) { 
     dta <- data.frame(cbind(data, object$subclass)) 
     names(dta) <- c(names(data), subclass) 
     data <- dta 
    } 
    if (group == "all") 
     return(data[wt > 0, ]) 
    else if (group == "treat") 
     return(data[wt > 0 & treat == 1, ]) 
    else if (group == "control") 
     return(data[wt > 0 & treat == 0, ]) 
    else stop("error: invalid input for group.") 
} 
<bytecode: 0x00000000866125e0> 
<environment: namespace:MatchIt> 

 

> matchit 
function (formula, data, method = "nearest", distance = "logit", 
    distance.options = list(), discard = "none", reestimate = FALSE, 
    ...) 
{ 
    mcall <- match.call() 
    if (is.null(data)) 
     stop("Dataframe must be specified", call. = FALSE) 
    if (!is.data.frame(data)) { 
     stop("Data must be a dataframe", call. = FALSE) 
    } 
    if (sum(is.na(data)) > 0) 
     stop("Missing values exist in the data") 
    ischar <- rep(0, dim(data)[2]) 
    for (i in 1:dim(data)[2]) if (is.character(data[, i])) 
     data[, i] <- as.factor(data[, i]) 
    if (!is.numeric(distance)) { 
     fn1 <- paste("distance2", distance, sep = "") 
     if (!exists(fn1)) 
      stop(distance, "not supported.") 
    } 
    if (is.numeric(distance)) { 
     fn1 <- "distance2user" 
    } 
    fn2 <- paste("matchit2", method, sep = "") 
    if (!exists(fn2)) 
     stop(method, "not supported.") 
    tryerror <- try(model.frame(formula), TRUE) 
    if (distance %in% c("GAMlogit", "GAMprobit", "GAMcloglog", 
     "GAMlog", "GAMcauchit")) { 
     requireNamespace("mgcv") 
     tt <- terms(mgcv::interpret.gam(formula)$fake.formula) 
    } 
    else { 
     tt <- terms(formula) 
    } 
    attr(tt, "intercept") <- 0 
    mf <- model.frame(tt, data) 
    treat <- model.response(mf) 
    X <- model.matrix(tt, data = mf) 
    if (method == "exact") { 
     distance <- out1 <- discarded <- NULL 
     if (!is.null(distance)) 
      warning("distance is set to `NULL' when exact matching is used.") 
    } 
    else if (is.numeric(distance)) { 
     out1 <- NULL 
     discarded <- discard(treat, distance, discard, X) 
    } 
    else { 
     if (is.null(distance.options$formula)) 
      distance.options$formula <- formula 
     if (is.null(distance.options$data)) 
      distance.options$data <- data 
     out1 <- do.call(fn1, distance.options) 
     discarded <- discard(treat, out1$distance, discard, X) 
     if (reestimate) { 
      distance.options$data <- data[!discarded, ] 
      distance.options$weights <- distance.options$weights[!discarded] 
      tmp <- out1 
      out1 <- do.call(fn1, distance.options) 
      tmp$distance[!discarded] <- out1$distance 
      out1$distance <- tmp$distance 
     } 
     distance <- out1$distance 
    } 
    if (fn1 == "distance2mahalanobis") { 
     is.full.mahalanobis <- TRUE 
    } 
    else { 
     is.full.mahalanobis <- FALSE 
    } 
    out2 <- do.call(fn2, list(treat, X, data, distance = distance, 
     discarded, is.full.mahalanobis = is.full.mahalanobis, 
     ...)) 
    if (fn1 == "distance2mahalanobis") { 
     distance[1:length(distance)] <- NA 
     class(out2) <- c("matchit.mahalanobis", "matchit") 
    } 
    out2$call <- mcall 
    out2$model <- out1$model 
    out2$formula <- formula 
    out2$treat <- treat 
    if (is.null(out2$X)) { 
     out2$X <- X 
    } 
    out2$distance <- distance 
    out2$discarded <- discarded 
    nn <- matrix(0, ncol = 2, nrow = 4) 
    nn[1, ] <- c(sum(out2$treat == 0), sum(out2$treat == 1)) 
    nn[2, ] <- c(sum(out2$treat == 0 & out2$weights > 0), sum(out2$treat == 
     1 & out2$weights > 0)) 
    nn[3, ] <- c(sum(out2$treat == 0 & out2$weights == 0 & out2$discarded == 
     0), sum(out2$treat == 1 & out2$weights == 0 & out2$discarded == 
     0)) 
    nn[4, ] <- c(sum(out2$treat == 0 & out2$weights == 0 & out2$discarded == 
     1), sum(out2$treat == 1 & out2$weights == 0 & out2$discarded == 
     1)) 
    dimnames(nn) <- list(c("All", "Matched", "Unmatched", "Discarded"), 
     c("Control", "Treated")) 
    out2$nn <- nn 
    return(out2) 
} 
<bytecode: 0x0000000086d6e158> 
<environment: namespace:MatchIt> 

答えて

3

は、第一に、それは2つのシナリオの主な違いであるsubsittutionが、実際それではないことに注意してください非置換の場合、コードはmatchitを呼び出す関数の式を定義しますが、代入その関数の外の式を定義します。どちらの場合も、式が関数の外で定義されていれば失敗し、どちらの場合も式が関数内で定義されていれば機能します。

問題は、式が関数の外で定義されていたので、我々はそれがどこに匿名関数内のローカル環境になりたいのに対し、例の式の環境は、地球環境

environment(WL.FM) 
## <environment: R_GlobalEnv> 

であるということです使用されている。あなたはこの代替しようと機能で式を定義したくない場合は

m.match.1 <- lapply(WL, function(x) { 
    WL.FM <- reformulate(wl.cov, response = "group") 
    matchit(WL.FM, data = x) 
}) 
match <- lapply(m.match.1, match.data) 

2)のか:

WL.FM <- reformulate(wl.cov, response = "group") 
m.match.1 <- lapply(WL, function(x) { 
    environment(WL.FM) <- environment() 
    matchit(WL.FM, data = x) 
}) 
match <- lapply(m.match.1, match.data) 

2a)を

1)これを試してみてください環境をリセットする別の方法は、数式を文字に変換して式に戻すことです。

WL.FM <- reformulate(wl.cov, response = "group") 
m.match.1 <- lapply(WL, function(x) { 
    WL.FM <- formula(format(WL.FM)) 
    matchit(WL.FM, data = x) 
}) 
match <- lapply(m.match.1, match.data) 

3)さらに別のアプローチは、WL.FMを数式オブジェクトではなく文字列として定義することです。それから環境はありません。その環境がデフォルトになります。その場合には無名関数の数式に変換します

WL.FM <- format(reformulate(wl.cov, response = "group")) # character 
m.match.1 <- lapply(WL, function(x) matchit(formula(WL.FM), data = x)) 
match <- lapply(m.match.1, match.data) 

注:重要な問題に関連していないが、ビューのスタイルの観点から、上記の中で我々は削除しましたrequireステートメントコードの先頭に単一のlibraryステートメントを使用し、ifステートメント内にない限り、requireは使用しないでください。 - if (require(...)) ...ロードするパッケージが利用できない場合、できるだけ早い段階でコードを失敗させたい。

また、lapplyコードを、それぞれの場合に添字を反復するのではなく、WLm.match.1を反復処理するように変更しました。

関連する問題