这里有一些绘制两个变量的方法。由于您没有提供数据,我将从 R 包含的数据集中提取一些数据:
data(iris)
iris.sub <- subset(iris, subset=Species!="versicolor", select=c(Species, Sepal.Length, Sepal.Width))
iris.sub <- droplevels(iris.sub)
set.seed(42)
iris.sub$Sepal.Length <- iris.sub$Sepal.Length + rnorm(100, 0, .5)
iris.sub$Sepal.Width <- iris.sub$Sepal.Width + rnorm(100, 0, .5)
str(iris.sub)
# 'data.frame': 100 obs. of 3 variables:
# $ Species : Factor w/ 2 levels "setosa","virginica": 1 1 1 1 1 1 1 1 1 1 ...
# $ Sepal.Length: num 5.79 4.62 4.88 4.92 5.2 ...
# $ Sepal.Width : num 4.1 3.52 2.7 4.02 3.27 ...
我们需要删除其中一个物种进行逻辑回归。 iris 测量值也有很大重叠,所以我给它们添加了一些噪音。这就是他们的样子:
clr <- as.numeric(iris.sub$Species) + 2
plot(Sepal.Length~Sepal.Width, iris.sub, pch=16, cex=1.5, col=clr)
legend("bottomleft", c("setosa", "virginica"), pch=16, cex=1.25, col=3:4)
现在是逻辑回归:
iris.glm <- glm(Species~Sepal.Length+Sepal.Width, iris.sub, family="binomial")
prob.vir <- predict(iris.glm, type="resp")
boxplot(prob.vir~Species, iris.sub, ylab="Probability virginica")
virginica <- as.numeric(iris.sub$Species) - 1
箱线图只是一个双重检查,以确保预测是针对第二类virginica。现在我们可以绘制每个变量:
oldp <- par(mfcol=c(2, 1), mar=c(3.1, 4.1, 1.1, 2.1), mgp=c(2, 1, 0))
plot(virginica~Sepal.Length, iris.sub, ylab="Probability virginica", pch=16, col=clr)
x1 <- seq(min(iris.sub$Sepal.Length), max(iris.sub$Sepal.Length), length.out=50)
y1 <- predict(iris.glm, data.frame(Sepal.Length=x1, Sepal.Width=mean(iris.sub$Sepal.Width)), type="resp")
lines(x1, y1)
plot(virginica~Sepal.Width, iris.sub, ylab="Probability virginica", pch=16, col=clr)
x2 <- seq(min(iris.sub$Sepal.Width), max(iris.sub$Sepal.Width), length.out=50)
y2 <- predict(iris.glm, data.frame(Sepal.Width=x2, Sepal.Length=mean(iris.sub$Sepal.Length)), type="resp")
lines(x2, y2)
par(oldp)
陡峭的曲线表明物种之间的断裂更明显,渐变的曲线表明更广泛的重叠。这些曲线是在未绘制的变量的平均值处生成的。例如,您可以在四分位数添加曲线以获得更多细节。
scatterplot3d 函数可以同时显示两个变量:
library(scatterplot3d)
plt <- scatterplot3d(iris.sub$Sepal.Length, iris.sub$Sepal.Width, predict(iris.glm, type="resp"),
xlab="Sepal.Length", ylab="Sepal.Width", zlab="Probability of viginica",
scale.y=.75, angle=160, pch=16, color=clr)
surf <- function(x, y) predict(iris.glm, data.frame(Sepal.Length=x, Sepal.Width=y), type="resp")
plt$contour3d(surf, col="darkgray")
最后,您可以使用等高线图来显示组之间的边界:
X <- expand.grid(x=x1, y=x2)
z <- predict(iris.glm, data.frame(Sepal.Length=X$x, Sepal.Width=X$y), type="resp")
plot(Sepal.Length~Sepal.Width, iris.sub, xlab="Sepal.Width", ylab="Sepal.Length", pch=16, col=clr)
legend("bottomleft", c("setosa", "virginica"), pch=16, cex=1.25, col=3:4)
contour(x2, x1, matrix(z, 50, 50, byrow=TRUE), levels=c(.05, .1, .5, .9, .95), add=TRUE)