使用R中的sample.split错误地拆分数据并使用逻辑回归进行问题

时间:2017-11-29 07:35:49

标签: r glm data-partitioning

我有2个问题。

  1. 当我尝试将数据拆分为测试和训练集时,使用sample.split如下所示,抽样相当不明确。我的意思是数据d的长度为392,因此,4:1除法应显示0.8 * 392 = 313.6,即测试集中的313或314行,但显示的长度为304.有什么我可能的不见了?

    require(caTools)
    set.seed(101)
    samplev = sample.split(d[,], SplitRatio= 0.80)
    train = subset(d, samplev == TRUE)
    test = subset(d, samplev == FALSE)
    
  2. 我尝试按如下方式使用拆分数据进行R中的逻辑回归任务,如下所示 -

    #Training
    m <- glm(mpg01~ . -name, data= train, family = binomial(link = 'logit'))
    out2 <- predict.glm(m, test, type = "response")
    class2 <- vector()
    for (i in 1:length(out2))
    {
      if(out2[i] >= 0.5)
      {
        class2[i] <- 1
      }
      else
      {
        class2[i] <- 0
      }
    }
    r2 <- table(class2, test$mpg01)  #confusion Matrix
    
  3. 我们的想法是不要使用&#39; name&#39;培训数据中的列。当我尝试在测试数据上运行构建的模型时,它显示以下内容 -

      

    out2&lt; - predict.glm(m,test,type =&#34; response&#34;)

         
        

    model.frame.default中的错误(条款,newdata,na.action = na.action,xlev = object $ xlevels):

             
          

    因子名称有新级别amc ambassador sst,amc concord dl 6,amc pacer,amc pacer d / l,amc rebel sst,audi 100 ls,audi 5000,buick century 350,buick century limited,cadillac seville,capri ii ,雪佛兰bel air,雪佛兰骑士,雪佛兰骑士旅行车,雪佛兰蒙特卡洛,雪佛兰维加2300,克莱斯勒lebaron town @ country(sw),克莱斯勒新约克brougham,datsun 510掀背车,datsun b210 gx,datsun f-10两厢车,闪避白羊座马车(sw),闪避白杨6,闪避柯尔特硬顶,闪避马驹m / m,道奇飞镖定制,道奇马格姆xe,道奇横冲直撞,菲亚特124 tc,福特野马,福特野马ii,福特游侠,本田思域1500 gl,maxda rx3,mazda 626,mazda glc 4,mazda glc custom,mercedes-benz 240d,mercedes-benz 280s,mercury capri 2000,mercury marquis,oldsmobile cutlass ciera(柴油),peugeot 505s turbo diesel,plymouth&#39; cuda 340,普利茅斯狂暴格兰德轿车,普利茅斯大怒,普利茅斯地平线,普利茅斯地平线守财奴,普利茅斯地平线tc3,普利茅斯卫星,plymo

        
      

    根据我的理解,不应该显示此错误,因为我们没有使用&#39;名称&#39;属性?或者,如果我们以某种方式使用它,当它没有意图时,我做错了什么?

1 个答案:

答案 0 :(得分:2)

问题1答案

sample.split函数期望第一个参数有一个向量,看起来你传递的是data.framematrix。这是一个显示不同行为的简单示例。

# Mock up some data
library(caTools)
df0 <- data.frame(
     y = as.factor(rbinom(392, 1, 0.75)),
     x1 = rnorm(392)
)

# sample.split with a data.frame as the first argument does not split 80/20 as expected
set.seed(101)
samplev = sample.split(df0, SplitRatio= 0.80)
train = subset(df0, samplev == TRUE)
test = subset(df0, samplev == FALSE)
nrow(train)
[1] 196
nrow(test)
[1] 196

# feed in your response variable as a vector to get the expected split
set.seed(101)
samplev = sample.split(df0$y, SplitRatio= 0.80)
train = subset(df0, samplev == TRUE)
test = subset(df0, samplev == FALSE)
nrow(train)
[1] 314
nrow(test)
[1] 78

问题2答案

虽然你所做的事情似乎是合理的,并且看起来它应该按照你期望的方式工作,但似乎并不是glm和最终model.frame函数如何处理引导下的公式。

首先,这里的代码将重现您正在做的事情以及您所看到的错误。

set.seed(123)
df <- data.frame(
    y = as.factor(rbinom(100, 1, 0.5)),
    x1 = rnorm(100),
    x2 = rnorm(100),
    name = c(rep('a',40), rep('b',30), rep('c', 30))
)
train <- df[1:70,]
test <- df[71:100,]
m <- glm(y~ . -name, data= train, family = binomial(link = 'logit'))
out2 <- predict.glm(m, test, type = "response")

现在请注意,当我直接使用您的公式致电model.frame时,它仍然包含name列。

head(model.frame(y~ . -name, data = train), 1)
  y        x1        x2 name
1 0 0.2533185 0.7877388    a

而不包含.列符号的公式将不包含该额外列。

head(model.frame(y~ x1 + x2, data = train), 1)
  y        x1        x2
1 0 0.2533185 0.7877388

在一天结束时,您似乎需要通过直接在公式中指定列,或者如果您继续使用.列符号,然后通过删除来解决此问题您要排除的列。

更具体地说,通过我的简单示例,解决方法1看起来像。

m <- glm(y~ x1 + x2, data= train, family = binomial(link = 'logit'))
out2 <- predict.glm(m, test, type = "response")

解决方法选项2看起来像。

m <- glm(y~ ., data= train[,names(train) != 'name'], family = binomial(link = 'logit'))
out2 <- predict.glm(m, test, type = "response")