在 R 中使用 sample.split 的数据分割不正确以及逻辑回归问题
Incorrect splitting of data using sample.split in R and issue with logistic regression
我有 2 个问题。
当我尝试将我的数据拆分为测试集和训练集时,使用 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)
我正在尝试将拆分数据如下用于 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
想法是不使用数据中的 'name' 列进行训练。当我尝试 运行 测试数据上的构建模型时,它显示以下内容-
out2 <- predict.glm(m, test, type = "response")
Error in model.frame.default(Terms, newdata, na.action = na.action, xlev = object$xlevels) :
factor name has new levels 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, chevrolet bel air, chevrolet cavalier, chevrolet cavalier wagon, chevrolet monte carlo, chevrolet vega 2300, chrysler lebaron town @ country (sw), chrysler new yorker brougham, datsun 510 hatchback, datsun b210 gx, datsun f-10 hatchback, dodge aries wagon (sw), dodge aspen 6, dodge colt hardtop, dodge colt m/m, dodge dart custom, dodge magnum xe, dodge rampage, fiat 124 tc, ford mustang, ford mustang ii, ford ranger, honda civic 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 (diesel), peugeot 505s turbo diesel, plymouth 'cuda 340, plymouth fury gran sedan, plymouth grand fury, plymouth horizon, plymouth horizon miser, plymouth horizon tc3, plymouth satellite, plymo
根据我的理解,因为我们没有使用 'names' 属性,所以不应该出现这个错误吗?或者,如果我们在不打算使用它的情况下以某种方式使用它,我做错了什么?
问题 1 回答
sample.split 函数需要一个向量作为第一个参数,看起来您传递的是 data.frame
或 matrix
。这是一个显示不同行为的简单示例。
# 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")
我有 2 个问题。
当我尝试将我的数据拆分为测试集和训练集时,使用
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)
我正在尝试将拆分数据如下用于 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
想法是不使用数据中的 'name' 列进行训练。当我尝试 运行 测试数据上的构建模型时,它显示以下内容-
out2 <- predict.glm(m, test, type = "response")
Error in model.frame.default(Terms, newdata, na.action = na.action, xlev = object$xlevels) :
factor name has new levels 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, chevrolet bel air, chevrolet cavalier, chevrolet cavalier wagon, chevrolet monte carlo, chevrolet vega 2300, chrysler lebaron town @ country (sw), chrysler new yorker brougham, datsun 510 hatchback, datsun b210 gx, datsun f-10 hatchback, dodge aries wagon (sw), dodge aspen 6, dodge colt hardtop, dodge colt m/m, dodge dart custom, dodge magnum xe, dodge rampage, fiat 124 tc, ford mustang, ford mustang ii, ford ranger, honda civic 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 (diesel), peugeot 505s turbo diesel, plymouth 'cuda 340, plymouth fury gran sedan, plymouth grand fury, plymouth horizon, plymouth horizon miser, plymouth horizon tc3, plymouth satellite, plymo
根据我的理解,因为我们没有使用 'names' 属性,所以不应该出现这个错误吗?或者,如果我们在不打算使用它的情况下以某种方式使用它,我做错了什么?
问题 1 回答
sample.split 函数需要一个向量作为第一个参数,看起来您传递的是 data.frame
或 matrix
。这是一个显示不同行为的简单示例。
# 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")