r - 基于lm规范在数据集中自动创建变量
问题描述
我有一个如下所示的数据集:
outcome <- c(1,2, 2, 1, 2, 2, 2, 1)
city <- rep(c("A", "B"),4)
year <- c(2000, 2001, 2000, 2000, 2000, 2001, 2001, 2000)
educ <- c("high", "low", "low", "low", "high", "high", "high", "low")
age <- c(25,35, 30, 29, 31, 40, 20, 23)
area <- c("city", "sub", "sub", "sub", "city", "city", "city", "city")
peopleinhouse <- c(2,4, 3, 3, 5, 2, 1, 2)
adataset <- data.frame(outcome, city, year, educ, age, area, peopleinhouse, stringsAsFactors = FALSE)
我有一个向量如下:
avector <- c("outcome", "as.factor(city)", "year", "as.factor(educ):age", "log(age)", "as.factor(area):peopleinhouse")
我想自动化创建新(交互)变量的过程,avector
并adataset
作为输入和anotherdataset
输出。
我开始如下:
avector <- unlist(strsplit(avector , split=':', fixed=TRUE))
for (i in 1:length(avector)) {
if (substr(avector[i], start = 1, stop = 9) == "as.factor") {
adataset[,i] <- as.factor(adataset[,i])
} else if(substr(avector[i], start = 1, stop = 3) == "log") {
adataset[,i] <- log(adataset[,i])
} else if (substr(avector [i], start = 1, stop = 1) == "I") {
# Assumes a quadratic
adataset[,i] <- adataset[,i]*adataset[,i]
}
}
(这应该适用于单个变量(适用于我的实际数据),但我Error in Math.factor(adataset[, i]) : ‘log’ not meaningful for factors
在示例中得到错误)
但我不确定如何自动处理交互条款。
由于ivmodel
来自 library ,我需要交互项是一个变量ivmodel
。
所需的输出将是一个数据集,其中包含交互项作为变量:
as.factor(educ):age
并as.factor(area):peopleinhouse
作为一个变量。
有任何想法吗?
编辑:
我目前正朝着以下方向前进:
# For every entry in the vector
for (i in 1:length(avector)) {
# if there is a ":" in the entry
if (grepl(":", avector[i], fixed = FALSE)) {
# split the string into two string
tmp <- unlist(strsplit(avector[i], split=':', fixed=FALSE))
# make a new variable
adataset[,(length(avector)+i)] <- adataset[,tmp[1]]*adataset[,tmp[2]]
# Change the name of the new variable
names(adataset[,(length(avector)+i)]) <- paste0(names(tmp[1]), names(tmp[2]))
}
}
但是我无法正确使用语法..
编辑二:
ivmodelFormula
@Edo 在接受公式的评论中指出。这消除了我的部分问题。然而?ivmodelFormula
表明,对于多种工具,这些工具仍然由 (a) 向量提供:
# Multiple instruments
Z = card.data[,c("nearc4","nearc2")]
card.model2IV = ivmodelFormula(lwage ~ educ + exper + expersq + black +
south + smsa + reg661 +
reg662 + reg663 + reg664 +
reg665 + reg666 + reg667 +
reg668 + smsa66 | nearc4 + nearc2 +
exper + expersq + black +
south + smsa + reg661 +
reg662 + reg663 + reg664 +
reg665 + reg666 + reg667 +
reg668 + smsa66,data=card.data)
card.model2IV
例如,假设我想运行:
require(ivmodel)
Z <- adataset[, c("area", "educ", "peopleinhouse") ]
card.model2IV = ivmodelFormula(outcome ~ log(age) + as.factor(city) + year | area + educ + as.factor(city) + year)
card.model2IV
这样可行..
但是,如果我想以area:educ
交互方式运行,例如:
require(ivmodel)
Z <- adataset[, c("area", "educ", "peopleinhouse")]
another_card.model2IV = ivmodelFormula(outcome ~ log(age) + as.factor(city) + year | area:educ+ as.factor(city) + year)
another_card.model2IV
它运行,但它给了我与 相同的输出card.model2IV
,所以我仍然必须与数据中的工具进行交互。
解决方案
为了总结我们在评论中的讨论,我将给出最终答案。希望对其他将要查找此内容的用户有用。
答案分为三部分:第一部分与第一个问题的解决方案有关,第二部分与@Tom面临的实际问题有关,第三部分与使用其他包完成@Tom的有关实际目标。
第一部分
最初,问题是在给定初始数据集和字符串向量的情况下自动创建具有特定交互和转换的数据集。
解决问题的好方法是model.matrix
按照@krfurlong 的建议使用。
例如以这种方式。
给定以下数据:
outcome <- c(1,2, 2, 1, 2, 2, 2, 1)
city <- rep(c("A", "B"),4)
year <- c(2000, 2001, 2000, 2000, 2000, 2001, 2001, 2000)
educ <- c("high", "low", "low", "low", "high", "high", "high", "low")
age <- c(25,35, 30, 29, 31, 40, 20, 23)
area <- c("city", "sub", "sub", "sub", "city", "city", "city", "city")
peopleinhouse <- c(2,4, 3, 3, 5, 2, 1, 2)
adataset <- data.frame(outcome, city, year, educ, age, area, peopleinhouse, stringsAsFactors = FALSE)
avector <- c("outcome", "as.factor(city)", "year", "as.factor(educ):age", "log(age)", "as.factor(area):peopleinhouse")
您可以通过以下方式实现您的目标:
make_formula <- function(vec){
x <- paste(vec[-1], collapse = " + ")
frm <- paste(vec[1], x, sep = " ~ ")
as.formula(frm)
}
as.data.frame(model.matrix(make_formula(avector), adataset))
(Intercept) as.factor(city)B year log(age) as.factor(educ)high:age as.factor(educ)low:age as.factor(area)city:peopleinhouse as.factor(area)sub:peopleinhouse
1 1 0 2000 3.218876 25 0 2 0
2 1 1 2001 3.555348 0 35 0 4
3 1 0 2000 3.401197 0 30 0 3
4 1 1 2000 3.367296 0 29 0 3
5 1 0 2000 3.433987 31 0 5 0
6 1 1 2001 3.688879 40 0 2 0
7 1 0 2001 2.995732 20 0 1 0
8 1 1 2000 3.135494 0 23 2 0
第二部分
最终,我们发现@Tom 的实际目标是运行带有 package.json 的特定模型ivmodel
。
解决此问题的最佳方法是使用ivmodel
调用的本机函数,该函数ivmodelFormula
允许您设置处理转换和交互的公式。
例如以这种方式。
library(ivmodel)
card.model2IV <- ivmodelFormula(outcome ~ log(age) + as.factor(city) + year | area + educ + as.factor(city) + year)
another_card.model2IV <- ivmodelFormula(outcome ~ log(age) + as.factor(city) + year | area:educ+ as.factor(city) + year)
尽管在这种特定情况下打印的输出可能看起来相同,但可以注意到all.equal(card.model2IV, another_card.model2IV)
并非如此TRUE
,具体而言card.model2IV$Z
,another_card.model2IV$Z
看起来与预期的一样。
card.model2IV$Z
#> 8 x 2 sparse Matrix of class "dgCMatrix"
#> areasub educlow
#> 1 . .
#> 2 1 1
#> 3 1 1
#> 4 1 1
#> 5 . .
#> 6 . .
#> 7 . .
#> 8 . 1
another_card.model2IV$Z
#> 8 x 4 sparse Matrix of class "dgCMatrix"
#> areacity.educhigh areasub.educhigh areacity.educlow areasub.educlow
#> 1 1 . . .
#> 2 . . . 1
#> 3 . . . 1
#> 4 . . . 1
#> 5 1 . . .
#> 6 1 . . .
#> 7 1 . . .
#> 8 . . 1 .
第三方
最后,我们发现该包不处理多个插桩变量。
看到我不是该主题的专家,如果其他用户对此有更多了解,他们可能会随时更新此答案以使其更有用。
还有其他包可以处理这种模型。
查看:
推荐阅读
- python - 在 Python 中,是否有一个内置函数来获取两个给定值之间的值(在列表中)?
- verilog - 多位门
- node.js - 为什么我的 XMLHttpRequest POST 并不总是发送到服务器?
- python - 如何在opencv python中放置停留时间
- javascript - React Usestate 将状态设置为 false,我正在使用其中包含对象的数组
- php - 需要 curl 等待响应直到下一次执行
- c# - 在 dotnet core 3.1 中使用 IAuthorizationPolicyProvider 的自定义实现进行身份验证
- node.js - MongoDB - 我怎样才能获得最高的 Int
- reactjs - ReactJS 中的递增/递减函数
- excel - 将文件从一个文件夹移动到另一个文件夹 - 错误 53 找不到文件