caret::predict 给出错误:$ 运算符对原子向量无效

Posted

技术标签:

【中文标题】caret::predict 给出错误:$ 运算符对原子向量无效【英文标题】:caret::predict giving Error: $ operator is invalid for atomic vectors 【发布时间】:2021-07-11 19:58:27 【问题描述】:

这让我发疯了,我整天都在浏览类似的帖子,但似乎无法解决我的问题。我有一个经过训练并存储为model 的朴素贝叶斯模型。我正在尝试使用newdata 数据框进行预测,但我不断收到错误 Error: $ operator is invalid for atomic vectors。这是我正在运行的内容:stats::predict(model, newdata = newdata) 其中newdata 是另一个数据框的第一行:new data <- pbp[1, c("balls", "strikes", "outs_when_up", "stand", "pitcher", "p_throws", "inning")]

class(newdata) 给出[1] "tbl_df" "tbl" "data.frame"

【问题讨论】:

如果您包含一个简单的reproducible example,其中包含可用于测试和验证可能解决方案的示例输入和所需输出,则更容易为您提供帮助。 我知道对不起,我想知道如何给你模型,但我不确定如何。我可以给你培训代码,但培训大约需要 6 个小时。会给你一个实际的newdata 值行吗? 也许我可以给你一个.Rdata文件的链接?试试这个谷歌链接,这个模型对于 Github 来说太大了。 drive.google.com/drive/folders/… 那真的没那么有用。也许使用内置数据集创建一个简单的示例,该示例显示您用于拟合模型和进行预测的代码。看看你是否能得到同样的错误信息。目前甚至不清楚model 是什么类型的对象。 这基本上是我拟合数据的方式,但我正在努力重现同样的错误。 model <- caret::train(iris[, 1:4], iris$Species, method = "nb", preProc = c("center", "scale")) newdata <- as_tibble(newdata) stats::predict(model, newdata = newdata[1, c("Sepal.Width", "Sepal.Length", "Petal.Length", "Petal.Width")]) 我添加了强制 tibble 的行,因为当我查询我使用的 newdata 时,它已经作为 tibble 回来了。 【参考方案1】:

问题在于使用的数据。它应该与训练中使用的levels 匹配。例如。如果我们使用从 trainingData 到 predict 的行之一,它确实有效

predict(model, head(model$trainingData, 1))
#[1] Curveball
#Levels: Changeup Curveball Fastball Sinker Slider

通过检查两个数据集的str,训练中的一些factor 列是character

str(model$trainingData)
'data.frame':   1277525 obs. of  7 variables:
 $ pitcher     : Factor w/ 1390 levels "112526","115629",..: 277 277 277 277 277 277 277 277 277 277 ...
 $ stand       : Factor w/ 2 levels "L","R": 1 1 2 2 2 2 2 1 1 1 ...
 $ p_throws    : Factor w/ 2 levels "L","R": 2 2 2 2 2 2 2 2 2 2 ...
 $ balls       : num  0 1 0 1 2 2 2 0 0 0 ...
 $ strikes     : num  0 0 0 0 0 1 2 0 1 2 ...
 $ outs_when_up: num  1 1 1 1 1 1 1 2 2 2 ...
 $ .outcome    : Factor w/ 5 levels "Changeup","Curveball",..: 3 4 1 4 1 5 5 1 1 5 ...

str(newdata)
tibble [1 × 6] (S3: tbl_df/tbl/data.frame)
 $ balls       : int 3
 $ strikes     : int 2
 $ outs_when_up: int 1
 $ stand       : chr "R"
 $ pitcher     : int 605200
 $ p_throws    : chr "R"

一种选择是使levelsfactor 类相同

nm1 <- intersect(names(model$trainingData), names(newdata))
nm2 <- names(which(sapply(model$trainingData[nm1], is.factor)))
newdata[nm2] <- Map(function(x, y) factor(x, levels = levels(y)), newdata[nm2], model$trainingData[nm2])

现在执行prediction

predict(model, newdata)
#[1] Sinker
#Levels: Changeup Curveball Fastball Sinker Slider

【讨论】:

不幸的是,这似乎仍然给我同样的错误。 好奇怪,我去看看关卡谢谢。 太棒了!你搞定了,显然当只有一行时,为 newdata 拉取的投手的 ID 默认为 int。非常感谢!

以上是关于caret::predict 给出错误:$ 运算符对原子向量无效的主要内容,如果未能解决你的问题,请参考以下文章

Firebase.initializeApp() 给出错误:空值检查运算符用于空值

Sql Query 在其中使用 row_number 时给出错误缺少运算符

C++:当我定义运算符时,所有成员函数都会给出隐式定义错误

在 C# 三元运算符中给出错误:只有赋值、调用、递增、递减和新对象表达式可以用作语句

SQL减去两列给出错误-数据类型的运算符无效。运算符等于减法,类型等于nvarchar

在C#三元运算符给出错误:只有赋值,调用,递增,递减和新对象表达式可用作语句