plm: использование fixef() для ручного расчета подгоночных значений для модели с фиксированными эффектами

Обратите внимание: я пытаюсь заставить код работать как с временными и индивидуальными фиксированными эффектами, так и с несбалансированным набором данных. Пример кода ниже работает со сбалансированным набором данных.

Смотрите также редактирование ниже, пожалуйста

Я пытаюсь вручную рассчитать подходящие значения модели с фиксированными эффектами (с индивидуальными и временными эффектами), используя plm пакет. Это больше упражнение, чтобы подтвердить, что я понимаю механику модели и комплектации, я знаю, что могу получить соответствующие значения из plm объект, из двух связанных вопросов ( здесь и здесь).

От plm виньетка (п.2), лежащая в основе модель:

y _it = alpha + beta _transposed * x _it + (mu _i + lambda _t + epsilon _it)

где mu_i - это отдельный компонент члена ошибки (он же "отдельный эффект"), а lambda_t - "эффект времени".

Фиксированные эффекты могут быть извлечены с помощью fixef() и я подумал, что мог бы использовать их (вместе с независимыми переменными) для вычисления подгоночных значений для модели, используя (с двумя независимыми переменными) таким образом:

подходит _it = альфа + бета _1 * x1 + бета _2 * x2 + mu _i + лямбда _t

Вот где я терплю неудачу - значения, которые я получаю, нигде не соответствуют подогнанным значениям (которые я получаю как разницу между фактическими значениями и остатками в модельном объекте). Для одного я не вижу alpha в любом месте. Я пытался играть с фиксированными эффектами, показанными как отличия от первого, среднего и т. Д., Но безуспешно.

Чего мне не хватает? Боюсь, это может быть неправильное понимание модели или ошибка в коде... Заранее спасибо.

PS: один из связанных вопросов подсказывает, что pmodel.response() должно быть связано с моей проблемой (и причина не существует plm.fit функции), но ее страница справки не помогает мне понять, что на самом деле делает эта функция, и я не могу найти примеров того, как интерпретировать результат, который она дает.

Спасибо!

Пример кода того, что я сделал:

library(data.table); library(plm)

set.seed(100)
DT <- data.table(CJ(id=c("a","b","c","d"), time=c(1:10)))
DT[, x1:=rnorm(40)]
DT[, x2:=rnorm(40)]
DT[, y:=x1 + 2*x2 + rnorm(40)/10]
DT <- DT[!(id=="a" & time==4)] # just to make it an unbalanced panel
setkey(DT, id, time)

summary(plmFEit <- plm(data=DT, id=c("id","time"), formula=y ~ x1 + x2, model="within", effect="twoways"))

# Extract the fitted values from the plm object
FV <- data.table(plmFEit$model, residuals=as.numeric(plmFEit$residuals))
FV[, y := as.numeric(y)]
FV[, x1 := as.numeric(x1)]
FV[, x2 := as.numeric(x2)]

DT <- merge(x=DT, y=FV, by=c("y","x1","x2"), all=TRUE)
DT[, fitted.plm := as.numeric(y) - as.numeric(residuals)]

FEI <- data.table(as.matrix(fixef(object=plmFEit, effect="individual", type="level")), keep.rownames=TRUE) # as.matrix needed to preserve the names?
setnames(FEI, c("id","fei"))
setkey(FEI, id)
setkey(DT, id)
DT <- DT[FEI] # merge the fei into the data, each id gets a single number for every row

FET <- data.table(as.matrix(fixef(object=plmFEit, effect="time", type="level")), keep.rownames=TRUE) # as.matrix needed to preserve the names?
setnames(FET, c("time","fet"))
FET[, time := as.integer(time)] # fixef returns time as character
setkey(FET, time)
setkey(DT, time)
DT <- DT[FET] # merge the fet into the data, each time gets a single number for every row

# calculate the fitted values (called calc to distinguish from those from plm)
DT[, fitted.calc := as.numeric(coef(plmFEit)[1] * x1 + coef(plmFEit)[2]*x2 + fei + fet)]
DT[, diff := as.numeric(fitted.plm - fitted.calc)]

all.equal(DT$fitted.plm, DT$fitted.calc)

Моя сессия выглядит следующим образом:

R version 3.2.2 (2015-08-14)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 8 x64 (build 9200)

locale:
[1] LC_COLLATE=English_United States.1252  LC_CTYPE=English_United States.1252    LC_MONETARY=English_United States.1252 LC_NUMERIC=C                          
[5] LC_TIME=English_United States.1252    

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] plm_1.4-0           Formula_1.2-1       RJSONIO_1.3-0       jsonlite_0.9.17     readxl_0.1.0.9000   data.table_1.9.7    bit64_0.9-5         bit_1.1-12          RevoUtilsMath_3.2.2

loaded via a namespace (and not attached):
 [1] bdsmatrix_1.3-2  Rcpp_0.12.1      lattice_0.20-33  zoo_1.7-12       MASS_7.3-44      grid_3.2.2       chron_2.3-47     nlme_3.1-122     curl_0.9.3       rstudioapi_0.3.1 sandwich_2.3-4  
[12] tools_3.2.2  

Изменить: (2015-02-22) Так как это вызвало некоторый интерес, я постараюсь уточнить дальше. Я пытался подогнать модель с "фиксированными эффектами" (она же "внутри" или "фиктивные переменные по методу наименьших квадратов", как это называет виньетка пакета plm на стр.3, верхний абзац) - один и тот же наклон (ы), разные перехваты.

Это то же самое, что и запуск обычной регрессии OLS после добавления макетов для time а также id, Используя приведенный ниже код, я могу продублировать соответствующие значения из plm пакет с использованием базы lm(), С помощью макетов ясно, что первые элементы как id, так и времени являются группой для сравнения. То, что я до сих пор не могу сделать, это как использовать средства plm пакет, чтобы сделать то же самое, я могу легко выполнить с помощью lm(),

# fit the same with lm() and match the fitted values to those from plm()
lmF <- lm(data = DT, formula = y ~ x1 + x2 + factor(time) + factor(id))
time.lm <- coef(lmF)[grep(x = names(coef(lmF)), pattern = "time", fixed = TRUE)]
time.lm <- c(0, unname(time.lm)) # no need for names, the position index corresponds to time

id.lm <- coef(lmF)[grep(x = names(coef(lmF)), pattern = "id", fixed = TRUE)]
id.lm <- c(0, unname(id.lm))
names(id.lm) <- c("a","b","c","d") # set names so that individual values can be looked up below when generating the fit

DT[, by=list(id, time), fitted.lm := coef(lmF)[["(Intercept)"]]  +  coef(lmF)[["x1"]] * x1  +  coef(lmF)[["x2"]] * x2  +  time.lm[[time]]  +  id.lm[[id]]]
all.equal(DT$fitted.plm, DT$fitted.lm)

Надеюсь, что это полезно для тех, кто может быть заинтересован. Вопрос может быть о том, как plm а также fixef разобраться с недостающим значением, которое я намеренно создал. Я пытался играть с type= параметр fixef но безрезультатно.

4 ответа

Это работает для несбалансированных данных с effect="individual" и время манекенов y ~ x +factor(year):

fitted <- pmodel.response(plm.model)-residuals(plm.model)

Я обнаружил, что это может вам помочь, поскольку решение lm() в моем случае не работало (у меня были разные коэффициенты по сравнению с пакетом plm)

Поэтому речь идет только о применении предложений авторов пакета plm здесь http://r.789695.n4.nabble.com/fitted-from-plm-td3003924.html

Итак, что я сделал, это просто подать заявку

plm.object <- plm(y ~ lag(y, 1) + z +z2, data = mdt, model= "within", effect="twoways")
fitted <- as.numeric(plm.object$model[[1]] - plm.object$residuals) 

где мне нужна функция as.numeric, так как мне нужно использовать ее как вектор для подключения для дальнейших манипуляций. Я также хочу отметить, что если ваша модель имеет зависимую переменную с запаздыванием в правой части, решение выше с as.numeric предоставляет вектор уже NET из пропущенных значений из-за задержки. Для меня это именно то, что мне нужно.

Я довольно близок к предложению Helix123 вычесть within_intercept (он включается в каждый из двух фиксированных эффектов, поэтому вам нужно исправить это).

В моих ошибках реконструкции есть очень внушительный паттерн: индивидуальный a всегда выключен на -0.004858712 (для каждого периода времени). Лица b, c, d всегда выключены на 0,002839703 для каждого периода времени, за исключением периода 4 (где нет наблюдения за a), где они выключены на -0.010981192.

Есть идеи? Похоже, что отдельные фиксированные эффекты отбрасываются дисбалансом. Перезапуск сбалансирован, работает правильно.

Полный код:

DT <- data.table(CJ(id=c("a","b","c","d"), time=c(1:10)))
DT[, x1:=rnorm(40)]
DT[, x2:=rnorm(40)]
DT[, y:= x1 + 2*x2 + rnorm(40)/10]
DT <- DT[!(id=="a" & time==4)] # just to make it an unbalanced panel
setkey(DT, id, time)

plmFEit <- plm(formula=y ~ x1 + x2,
               data=DT,
               index=c("id","time"),
               effect="twoways",
               model="within")

summary(plmFEit)

DT[, resids := residuals(plmFEit)]

FEI <- data.table(as.matrix(fixef(plmFEit, effect="individual", type="level")), keep.rownames=TRUE) # as.matrix needed to preserve the names?
setnames(FEI, c("id","fei"))
setkey(FEI, id)
setkey(DT, id)
DT <- DT[FEI] # merge the fei into the data, each id gets a single number for every row

FET <- data.table(as.matrix(fixef(plmFEit, effect="time", type="level")), keep.rownames=TRUE) # as.matrix needed to preserve the names?
setnames(FET, c("time","fet"))
FET[, time := as.integer(time)] # fixef returns time as character
setkey(FET, time)
setkey(DT, time)
DT <- DT[FET] # merge the fet into the data, each time gets a single number for every row

DT[, fitted.calc := plmFEit$coefficients[[1]] * x1 + plmFEit$coefficients[[2]] * x2 +
     fei + fet - within_intercept(plmFEit)]

DT[, myresids := y - fitted.calc]
DT[, myerr := resids - myresids]

Это то, что вы хотели? Извлечь фиксированные эффекты с помощью fixef и сопоставьте их с индивидуальным индексом. Вот пример для данных Грюнфельда:

data(Grunfeld, package = "plm")
fe <- plm(inv ~ value + capital, data=Grunfeld, model = "within")

temp <- merge(Grunfeld, data.frame(fixef_firm = names(fixef(fe)), fixef = as.numeric(fixef(fe))), all.x =T, by.x = c("firm"), by.y=c("fixef_firm"))
fitted_by_hand <- temp$fixef + fe$coefficients[1] * Grunfeld$value +  fe$coefficients[2] * Grunfeld$capital

fitted <- fe$model[ , 1] - fe$residuals

# just to remove attributs and specific classes 
fitted_by_hand <- as.numeric(fitted_by_hand)
fitted <- as.numeric(fitted)

all.equal(fitted, fitted_by_hand) # TRUE
cbind(fitted, fitted_by_hand) # see yourself
Другие вопросы по тегам