作者:艹尛鱈_695 | 来源:互联网 | 2023-02-05 19:14
一些建模功能,例如glmnet()
,要求(或仅允许)将数据作为预测器矩阵和响应矩阵(或向量)传递,如使用公式所示。在这些情况下,通常情况是该predict()
方法(例如predict.glmnet()
)要求newdata
参数提供一个预测器矩阵,该矩阵具有与训练模型相同的特征。
当数据框具有因子(R的分类数据类型)时,创建预测变量矩阵的便捷方法是使用该model.matrix()
函数,该函数会自动为分类变量创建虚拟特征:
# this is the dataframe and matrix I want to use to train the model
set.seed(1)
df <- data.frame(x1 = factor(sample(LETTERS[1:5], replace = T, 20)),
x2 = rnorm(20, 100, 5),
x3 = factor(sample(c("U","L"), replace = T, 20)),
y = rnorm(20, 10, 2))
mm <- model.matrix(y~., data = df)
但是,当我引入一个带有新观察结果的数据框时,它仅包含原始数据框中因子水平的一个子集,model.matrix()
(可预测地)返回一个具有不同虚拟特征的矩阵。无法使用此新矩阵,predict.glm()
因为它没有模型期望的相同功能:
# this is the dataframe and matrix I want to predict on
set.seed(1)
df_new <- data.frame(x1 = c("B", "C"),
x2 = rnorm(2, 100, 5),
x3 = c("L","U"))
mm_new <- model.matrix(~., data = df_new)
有没有一种方法可以保存从数据帧到模型矩阵的转换(创建所有必要的虚拟特征),以便我可以将该转换重新应用于将来的观察?在我上面的示例中,理想情况下这将导致mm_new
具有相同的功能名称,mm
以便predict()
可以接受mm_new
。
我想补充一点,我知道这种方法,它实质上建议在调用之前包括df_new
in中的观察结果。如果我有所有的观察结果,并且我只是训练和测试模型,那么这个工作很好。但是,新的观察只能在将来(在生产预测管道中)访问,并且我想避免为新的预测重新加载整个训练数据帧的开销。df
model.matrix()
1> ishak..:
我发现正是我的文档中需要可model.matrix
和model.frame
,并希望分享。在中有一个参数,它model.matrix
称为xlev
“用作被调用的model.frame
数据的参数model.frame
”。
如果model.matrix
调用model.frame
,则xlev
期望数据帧中每个因子的字符向量列表(列表元素名称为因子名称);否则为0。每个字符向量都包含构建model.matrix
具有与原始特征相同的虚拟特征的新特征所需的全套因子水平model.matrix
。
这是一个工作示例:
set.seed(1)
df <- data.frame(x1 = factor(sample(LETTERS[1:5], replace = T, 20)),
x2 = rnorm(20, 100, 5),
x3 = factor(sample(c("U","L"), replace = T, 20)),
y = rnorm(20, 10, 2))
mm <- model.matrix(y~., data = df)
# this is a list of levels for each factor in the original df
xlevs <- lapply(df[,sapply(df, is.factor), drop = F], function(j){
levels(j)
})
# this is a new df with only a subset of the levels of the original factors
df_new <- data.frame(x1 = c("B", "C"),
x2 = rnorm(2, 100, 5),
x3 = c("U","U"))
# calling "xlev = " builds out a model.matrix with identical levels as the original df
mm_new <- model.matrix(~., data = df_new[1,], xlev = xlevs)
请注意,此解决方案仅处理作为原始因子水平的子集的因子水平。它并非旨在处理新的因子水平。