model.frame.default 中的 R 错误:使用 lm 时对象不是矩阵
R Error in model.frame.default: object is not a matrix when using lm
对于可重现的例子:
test <- structure(list(IDcount = c(1, 1, 1, 1, 1, 2, 2, 2, 2, 2), year = c(1,
2, 3, 4, 5, 1, 2, 3, 4, 5), Otminus1 = c(-0.28, -0.28, -0.44,
-0.27, 0.23, -0.03, -0.06, -0.04, 0, 0.02), N.1 = c(NA, -0.1,
0.01, 0.1, -0.04, -0.04, -0.04, -0.04, -0.05, -0.05), N.2 = c(NA,
NA, -0.09, 0.11, 0.06, NA, -0.08, -0.08, -0.09, -0.09), N.3 = c(NA,
NA, NA, 0.01, 0.07, NA, NA, -0.12, -0.13, -0.13), N.4 = c(NA,
NA, NA, NA, -0.04, NA, NA, NA, -0.05, -0.05), N.5 = c(NA, NA,
NA, NA, NA, NA, NA, NA, NA, -0.13)), row.names = c(NA, -10L), groups = structure(list(
IDcount = c(1, 2), .rows = structure(list(1:5, 6:10), ptype = integer(0), class = c("vctrs_list_of",
"vctrs_vctr", "list"))), row.names = 1:2, class = c("tbl_df",
"tbl", "data.frame"), .drop = TRUE), class = c("grouped_df",
"tbl_df", "tbl", "data.frame"))
results <- structure(list(IDcount = c(1, 2), N.1 = c(NA, NA), N.2 = c(NA,
NA), N.3 = c(NA, NA), N.4 = c(NA, NA), N.5 = c(NA, NA)), row.names = c(NA,
-2L), class = "data.frame")
我正在执行 lm
回归而不截取嵌套 for 循环中的 data frame
“测试”,并使用以下代码将系数写入“结果”:
index <- colnames(test) %>% str_which("N.")
betas <- matrix(nrow=length(unique(test$IDcount)), ncol=2)
colnames(betas) <- c("Intercept", "beta")
for (j in colnames(test)[index]) {
for (i in 1:2) {
tmp <- test[test$IDcount==i, c("Otminus1", j)]
if(any(colSums(!is.na(tmp)) == 0)) next
betas[i,] <- coef(lm(Otminus1 ~ . -1, tmp))
}
betas <- data.frame(betas)
results[[j]] <- betas$beta
}
这非常有效。但我现在想切换出 y 和 x 变量,以便循环中的公式显示为:
betas[i,] <- coef(lm(. ~ Otminus1 -1, tmp))
但是这样做时我收到以下错误消息:
Error in model.frame.default(formula = . ~ Otminus1 - 1, data = tmp, drop.unused.levels = TRUE) :
Object is not a matrix
我试图通过引入来考虑这一点 as.matrix
:
betas[i,] <- coef(lm(. ~ Otminus1 -1, as.matrix(tmp)))
但是在执行此操作时我收到此错误:
Error in model.frame.default(formula = . ~ Otminus1 - 1, data = as.matrix(tmp), :
'data' must be a data frame not matrix or an array
我找到了 ,但我无法将其应用到我的示例中。
点 .
仅适用于公式的 RHS。原因可能是出现的歧义,如果数据集中有两个以上的列(与您的特殊情况相反)。您可以改用 reformulate
,这有助于创建用于 lm
.
的公式
for (j in colnames(test)[index]) {
for (i in 1:2) {
tmp <- test[test$IDcount == i, c("Otminus1", j)]
if(any(colSums(!is.na(tmp)) == 0))
betas[i, ] <- NA
else {
fo <- reformulate(names(tmp)[1], names(tmp)[2], intercept=FALSE)
betas[i,] <- coef(lm(fo, tmp))
}
}
betas <- data.frame(betas)
results[[j]] <- betas$beta
}
results
# IDcount N.1 N.2 N.3 N.4 N.5
# 1 1 -0.03167421 0.07420163 0.1065183 -0.173913 NA
# 2 2 0.64615385 1.10714286 1.1000000 -2.500000 -6.5
备选方案w/ofor
循环
这里是一种更像 R 的方式,不使用 for
循环。首先,我们为自变量和 IDcounts 创建两个需要的向量。使用 outer
我们 paste
可能的组合由 ,
,
分隔
i.vars <- grep("N.", names(test), value=TRUE)
n.IDcount <- 1:2
combs <- outer(i.vars, n.IDcount, paste, sep=",")
给出这个矩阵。
combs
# [,1] [,2]
# [1,] "N.1,1" "N.1,2"
# [2,] "N.2,1" "N.2,2"
# [3,] "N.3,1" "N.3,2"
# [4,] "N.4,1" "N.4,2"
# [5,] "N.5,1" "N.5,2"
现在我们通过 sapply
循环到 combs
,在 ,
处创建一个 strsplit
,使用第一个值作为 IV,第二个值子集 test
数据。不可能的迭代会产生错误(IDcount == 1
的 N.5
情况),因此我们使用 tryCatch
并让代码在这种情况下抛出 NA
。
res <- sapply(combs, function(v) {
x <- el(strsplit(v, ","))
tmp <- test[test$IDcount == x[2], ]
tryCatch(lm(as.formula(paste0(x[1], "~ Otminus1 - 1")), tmp)$coe,
error=function(e) NA)
})
最后我们将 res
ult 放入矩阵中。
matrix(res, 2, byrow=TRUE, dimnames=list(n.IDcount, i.vars))
# N.1 N.2 N.3 N.4 N.5
# 1 -0.03167421 0.07420163 0.1065183 -0.173913 NA
# 2 0.64615385 1.10714286 1.1000000 -2.500000 -6.5
对于可重现的例子:
test <- structure(list(IDcount = c(1, 1, 1, 1, 1, 2, 2, 2, 2, 2), year = c(1,
2, 3, 4, 5, 1, 2, 3, 4, 5), Otminus1 = c(-0.28, -0.28, -0.44,
-0.27, 0.23, -0.03, -0.06, -0.04, 0, 0.02), N.1 = c(NA, -0.1,
0.01, 0.1, -0.04, -0.04, -0.04, -0.04, -0.05, -0.05), N.2 = c(NA,
NA, -0.09, 0.11, 0.06, NA, -0.08, -0.08, -0.09, -0.09), N.3 = c(NA,
NA, NA, 0.01, 0.07, NA, NA, -0.12, -0.13, -0.13), N.4 = c(NA,
NA, NA, NA, -0.04, NA, NA, NA, -0.05, -0.05), N.5 = c(NA, NA,
NA, NA, NA, NA, NA, NA, NA, -0.13)), row.names = c(NA, -10L), groups = structure(list(
IDcount = c(1, 2), .rows = structure(list(1:5, 6:10), ptype = integer(0), class = c("vctrs_list_of",
"vctrs_vctr", "list"))), row.names = 1:2, class = c("tbl_df",
"tbl", "data.frame"), .drop = TRUE), class = c("grouped_df",
"tbl_df", "tbl", "data.frame"))
results <- structure(list(IDcount = c(1, 2), N.1 = c(NA, NA), N.2 = c(NA,
NA), N.3 = c(NA, NA), N.4 = c(NA, NA), N.5 = c(NA, NA)), row.names = c(NA,
-2L), class = "data.frame")
我正在执行 lm
回归而不截取嵌套 for 循环中的 data frame
“测试”,并使用以下代码将系数写入“结果”:
index <- colnames(test) %>% str_which("N.")
betas <- matrix(nrow=length(unique(test$IDcount)), ncol=2)
colnames(betas) <- c("Intercept", "beta")
for (j in colnames(test)[index]) {
for (i in 1:2) {
tmp <- test[test$IDcount==i, c("Otminus1", j)]
if(any(colSums(!is.na(tmp)) == 0)) next
betas[i,] <- coef(lm(Otminus1 ~ . -1, tmp))
}
betas <- data.frame(betas)
results[[j]] <- betas$beta
}
这非常有效。但我现在想切换出 y 和 x 变量,以便循环中的公式显示为:
betas[i,] <- coef(lm(. ~ Otminus1 -1, tmp))
但是这样做时我收到以下错误消息:
Error in model.frame.default(formula = . ~ Otminus1 - 1, data = tmp, drop.unused.levels = TRUE) :
Object is not a matrix
我试图通过引入来考虑这一点 as.matrix
:
betas[i,] <- coef(lm(. ~ Otminus1 -1, as.matrix(tmp)))
但是在执行此操作时我收到此错误:
Error in model.frame.default(formula = . ~ Otminus1 - 1, data = as.matrix(tmp), :
'data' must be a data frame not matrix or an array
我找到了
点 .
仅适用于公式的 RHS。原因可能是出现的歧义,如果数据集中有两个以上的列(与您的特殊情况相反)。您可以改用 reformulate
,这有助于创建用于 lm
.
for (j in colnames(test)[index]) {
for (i in 1:2) {
tmp <- test[test$IDcount == i, c("Otminus1", j)]
if(any(colSums(!is.na(tmp)) == 0))
betas[i, ] <- NA
else {
fo <- reformulate(names(tmp)[1], names(tmp)[2], intercept=FALSE)
betas[i,] <- coef(lm(fo, tmp))
}
}
betas <- data.frame(betas)
results[[j]] <- betas$beta
}
results
# IDcount N.1 N.2 N.3 N.4 N.5
# 1 1 -0.03167421 0.07420163 0.1065183 -0.173913 NA
# 2 2 0.64615385 1.10714286 1.1000000 -2.500000 -6.5
备选方案w/ofor
循环
这里是一种更像 R 的方式,不使用 for
循环。首先,我们为自变量和 IDcounts 创建两个需要的向量。使用 outer
我们 paste
可能的组合由 ,
,
i.vars <- grep("N.", names(test), value=TRUE)
n.IDcount <- 1:2
combs <- outer(i.vars, n.IDcount, paste, sep=",")
给出这个矩阵。
combs
# [,1] [,2]
# [1,] "N.1,1" "N.1,2"
# [2,] "N.2,1" "N.2,2"
# [3,] "N.3,1" "N.3,2"
# [4,] "N.4,1" "N.4,2"
# [5,] "N.5,1" "N.5,2"
现在我们通过 sapply
循环到 combs
,在 ,
处创建一个 strsplit
,使用第一个值作为 IV,第二个值子集 test
数据。不可能的迭代会产生错误(IDcount == 1
的 N.5
情况),因此我们使用 tryCatch
并让代码在这种情况下抛出 NA
。
res <- sapply(combs, function(v) {
x <- el(strsplit(v, ","))
tmp <- test[test$IDcount == x[2], ]
tryCatch(lm(as.formula(paste0(x[1], "~ Otminus1 - 1")), tmp)$coe,
error=function(e) NA)
})
最后我们将 res
ult 放入矩阵中。
matrix(res, 2, byrow=TRUE, dimnames=list(n.IDcount, i.vars))
# N.1 N.2 N.3 N.4 N.5
# 1 -0.03167421 0.07420163 0.1065183 -0.173913 NA
# 2 0.64615385 1.10714286 1.1000000 -2.500000 -6.5