【问题标题】:Why is R treating this data.frame object as a list?为什么 R 将此 data.frame 对象视为列表?
【发布时间】:2020-01-19 23:52:07
【问题描述】:

我正在尝试对我使用MASS 包将几个变量除以 R 中的附加缩放变量(此处未显示)创建的 data.frame 运行最小判别分析 (lda())。下面是一个示例数据集和我正在使用的重现错误的代码示例版本。

class   Var1    Var2    Var3    Var4
2   0.732459522 0.973014649 0.612952968 0.127216654
3   0.76692254  0.990230286 0.629448709 0.104675506
2   0.847487002 1.021663778 0.649046794 0.187175043
3   0.823583181 1.050274223 0.673674589 0.170018282
1   0.796279894 1.058458813 0.583702391 0.222320638
2   0.925681255 1.009909166 0.636663914 0.205615194
2   0.627334465 1.074702886 0.59762309  0.23344652
3   0.980376124 1.011447261 0.646770237 0.232215863
3   0.79342723  1.048826291 0.750234742 0.248826291
1   0.960655738 1.042622951 0.6 0.262295082
2   0.963788301 1.005571031 0.590529248 0.233983287
1   1.013157895 1.049342105 0.657894737 0.223684211
2   1.211538462 1.060897436 0.733974359 0.288461538
3   1.25083612  1.023411371 0.759197324 0.311036789
3   0.959196485 1.009416196 0.635907094 0.12868801
1   0.823681936 1.005185825 0.590319793 0.219533276
2   0.777508091 0.998381877 0.624595469 0.165048544
3   0.749114103 0.985825656 0.585400425 0.133947555
1   0.816999133 1.036426713 0.604509974 0.197745013
data<-read.csv("data.csv",header=TRUE)
data_train<-na.omit(data)
scores_train<-data_train[-c(1)]
lda_train<-lda(data_train$class~scores_train,prior = c(1,1,1)/3,CV=TRUE)
scores_test<-data[-c(1)]
lda_test<-predict(lda_train,as.data.frame(scores_test),prior = c(1,1,1)/3)

lda_train<-lda(data_train$class~as.matrix(scores_train),prior = c(1,1,1)/3,CV=TRUE)
class(scores_train)
class(scores_test)

当我尝试使用数据集执行 lda 时,我收到以下错误消息。

Error in model.frame.default(formula = data_train$class ~ scores_train) : 
  invalid type (list) for variable 'scores_train'

我可以通过使用as.matrix 将数据强制转换为矩阵格式来强制数据正常工作。值得注意的是,尝试使用as.data.frame()data.frame() 做类似的事情是行不通的。但是,当我尝试将生成的判别函数应用于整个数据集时,我收到以下消息...

Error in UseMethod("predict") : 
  no applicable method for 'predict' applied to an object of class "list"

但是,当我检查使用 class() 的对象的类时,它说这两个对象都是 data.frame 格式。我检查了数据集以查看是否有任何不完整的行或列可能导致它将它们视为一系列列表而不是单个 data.frame,但没有缺失值。同样,这似乎不是由于任何变量的名称。

我不确定为什么 R 将对象视为列表而不是 data.frame(从而导致最小判别分析失败),尤其是当它识别出对象属于 data.frame 类时。

【问题讨论】:

  • 对,我知道 data.frame 是一种特殊类型的列表,其中每列的条目数相同,但我不清楚为什么这会导致 lda() 失败,尤其是当我能够毫无问题地在其他 data.frame 对象上运行 lda() 时。同样,将新数据强制转换为矩阵格式会给我同样的错误信息。

标签: r lda mass


【解决方案1】:

对于 lda,您必须提供公式,因此如果您提供数据框,则以下内容有效:

lda_train<-lda(class ~ .,data=data_train,prior = c(1,1,1)/3,CV=TRUE)

如果您不提供公式,请执行以下操作:

lda(grouping=data_train$class,x=data_train[,-1],prior = c(1,1,1)/3, CV=TRUE)

当你使用 CV=TRUE 时,它使用 leave-one-out 交叉验证给你后验,但不幸的是它无法保留模型,你可以看到它:

class(lda_train)
[1] "list"

要进行预测,您需要使用 CV=FALSE 进行训练。您提供与用于训练的列具有相同列的 data.frame 或矩阵,在您的情况下,它将是:

lda_train<-lda(class ~ .,data=data_train,prior = c(1,1,1)/3)
data_test=data.frame(Var1=rnorm(10),Var2=rnorm(10),
Var3=rnorm(10),Var4=rnorm(10))
predict(lda_train,data_test)

对于MASS中的lda,没有可以从训练中获得超参数,所以也许你想详细说明一下为什么需要交叉验证?

如果您想探索它,以下是您可以为 lda 运行交叉验证的方法(注意使用 lda2):

data_train$class =factor(data$class)
lda_train = train(class ~ .,data=data_train,method="lda2",
trControl = trainControl(method = "cv"))
predict(lda_train,data_test)

【讨论】:

  • 这适用于初始测试数据集,谢谢。但是,鉴于predict.lda() 需要一个对象和新的数据框才能使用,那么如何将其应用于predict.lda() 函数?我正在尝试将此数据集应用于一个新数据集,以预测“类”未知的条目(为了空间,在上面的示例中省略了)。
  • 要进行预测,您需要提供具有相同列名的 data.frame 或矩阵。我现在将添加到我的示例中。
  • @user2352714 - predict 需要将对象作为 lda 对象传递(见下文)
  • 好的,我现在看到你的第二期了。我正在寻找在使用 CV=TRUE 时如何使用它。
  • 就是这样。我搞砸了将 CV=TRUE 放在训练函数中,而它只应该放在预测函数中。
【解决方案2】:

formula 参数正在寻找一个结构化公式来声明变量之间的关系。每个命名的变量必须是一个向量。您可以在声明数据参数时传递同一数据框中的所有名称:

lda(class ~ Var1 + Var2 + Var3 + Var4, 
    data = data, prior = c(1,1,1)/3, CV=TRUE)

或者单独传递列:

lda(data$class ~ scores_train$Var1 +  
      scores_train$Var2 + 
      scores_train$Var3 + 
      scores_train$Var4, 
    prior = c(1,1,1)/3, CV=TRUE)

对于predict不接受作为对象的问题,需要将CV改为FALSE,否则只会返回一个列表(不是predict需要的lda对象):

model <- lda(data$class ~ scores_train$Var1 +  
      scores_train$Var2 + 
      scores_train$Var3 + 
      scores_train$Var4, 
    prior = c(1,1,1)/3, CV=FALSE)

predict(model)

【讨论】:

    猜你喜欢
    • 2014-05-17
    • 2011-09-12
    • 1970-01-01
    • 2022-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-12
    • 2020-07-17
    相关资源
    最近更新 更多