使用ggplot2没有得到平滑的曲线
Not getting a smooth curve using ggplot2
我正在尝试使用 lme4
包来拟合混合效果模型。不幸的是,我无法分享我正在使用的数据。我也找不到与我的问题相关的玩具数据集。所以在这里我展示了我到目前为止遵循的步骤:
首先我绘制了数据的整体趋势如下:
p21 <- ggplot(data = sub_data, aes(x = age_cent, y = y))
p21+ geom_point() + geom_smooth()
基于此,数据中似乎存在某种非线性趋势。因此,我尝试如下拟合二次模型:
sub_data$age_cent=sub_data$age-mean((sub_data)$age)
sub_data$age_centsqr=(sub_data$age-mean((sub_data)$age))^2
m1= lmer(y ~ 1 + age_cent + age_centsqr +(1 | id) , sub_data, REML = TRUE)
在上面的模型中,我只包含了一个随机截距,因为我没有足够的数据来包含随机斜率和 intercept.Then 我提取了这些模型在人口水平上的预测如下:
pred1=predict(m1,re.form=NA)
接下来我绘制了这些预测以及像这样的平滑二次函数
p21+ geom_point() + geom_smooth(method = "lm", formula = y ~ I(x) + I(x^2)
,col="red")+geom_line(aes(y=pred1,group = id) ,col="blue", lwd = 0.5)
在上图中,对应于预测的曲线不平滑。任何人都可以帮我找出原因吗?
我在这里做错了什么?
更新:
正如 eipi10 指出的,这可能是由于为不同的人拟合了不同的曲线。
但是当我使用 lme4 包中的玩具数据集尝试同样的事情时,我得到了每个人的相同曲线,如下所示:
m1 <- lmer(Reaction ~ 1+I(Days) + (1+ Days| Subject) , data = sleepstudy)
pred1new1=predict(m1,re.form=NA)
p21 <- ggplot(data = sleepstudy, aes(x = Days, y = Reaction))
p21+ geom_point() + geom_smooth()
p21+ geom_point() + geom_smooth()+ geom_line(aes(y=pred1new1,group = Subject) ,col="red", lwd = 0.5)
不同结果的原因可能是什么?这是由于数据不平衡造成的吗?
我使用的数据是在 3 个时间步中收集的,有些人在所有 3 个时间步中都没有。但是toy数据集是平衡数据集
谢谢
tl;dr 使用 expand.grid()
或类似的东西为每个组生成一个 balanced/evenly 间隔样本(如果你有一个强非线性曲线你可能想要生成一组 larger/more 比原始数据间隔更小的 x 值)
您还可以查看 sjPlot
包,它会自动执行很多此类操作...
您需要不平衡数据集和固定效应的非线性(例如多项式)模型才能看到此效应。
- 如果模型是线性的,那么您不会注意到缺失值,因为
geom_line()
完成的线性插值非常完美
- 如果数据是平衡的,那么就没有间隙可以被线性插值奇怪地填充
生成具有二次效应和不平衡数据集的示例;适合模型
library(lme4)
set.seed(101)
dd <- expand.grid(id=factor(1:10),x=1:10)
dd$y <- simulate(~poly(x,2)+(poly(x,2)|id),
newdata=dd,
family=gaussian,
newparams=list(beta=c(0,0,0.1),
theta=rep(0.1,6),
sigma=1))[[1]]
## subsample randomly (missing values)
dd <- dd[sort(sample(nrow(dd),size=round(0.7*nrow(dd)))),]
m1 <- lmer(y ~ poly(x,2) + (poly(x,2)|id) , data = dd)
天真的预测和情节:
dd$pred1 <- predict(m1,re.form=NA)
library(ggplot2)
p11 <- (ggplot(data = dd, aes(x = x, y = y))
+ geom_point() + geom_smooth(method="lm",formula=y~poly(x,2))
)
p11 + geom_line(aes(y=pred1,group = id) ,col="red", lwd = 0.5)
现在生成一个平衡的数据集。此版本在最小值和最大值之间生成 51 个均匀间隔的点 - 如果原始数据间隔不均匀,这将很有用。如果您的 x
变量中有 NA 值,请不要忘记 na.rm=TRUE
...
pframe <- with(dd,expand.grid(id=levels(id),x=seq(min(x),max(x),length.out=51)
进行预测,并将其叠加在原始图上:
pframe$pred1 <- predict(m1,newdata=pframe,re.form=NA)
p11 + geom_line(data=pframe,aes(y=pred1,group = id) ,col="red", lwd = 0.5)
我正在尝试使用 lme4
包来拟合混合效果模型。不幸的是,我无法分享我正在使用的数据。我也找不到与我的问题相关的玩具数据集。所以在这里我展示了我到目前为止遵循的步骤:
首先我绘制了数据的整体趋势如下:
p21 <- ggplot(data = sub_data, aes(x = age_cent, y = y))
p21+ geom_point() + geom_smooth()
基于此,数据中似乎存在某种非线性趋势。因此,我尝试如下拟合二次模型:
sub_data$age_cent=sub_data$age-mean((sub_data)$age)
sub_data$age_centsqr=(sub_data$age-mean((sub_data)$age))^2
m1= lmer(y ~ 1 + age_cent + age_centsqr +(1 | id) , sub_data, REML = TRUE)
在上面的模型中,我只包含了一个随机截距,因为我没有足够的数据来包含随机斜率和 intercept.Then 我提取了这些模型在人口水平上的预测如下:
pred1=predict(m1,re.form=NA)
接下来我绘制了这些预测以及像这样的平滑二次函数
p21+ geom_point() + geom_smooth(method = "lm", formula = y ~ I(x) + I(x^2)
,col="red")+geom_line(aes(y=pred1,group = id) ,col="blue", lwd = 0.5)
在上图中,对应于预测的曲线不平滑。任何人都可以帮我找出原因吗? 我在这里做错了什么?
更新: 正如 eipi10 指出的,这可能是由于为不同的人拟合了不同的曲线。
但是当我使用 lme4 包中的玩具数据集尝试同样的事情时,我得到了每个人的相同曲线,如下所示:
m1 <- lmer(Reaction ~ 1+I(Days) + (1+ Days| Subject) , data = sleepstudy)
pred1new1=predict(m1,re.form=NA)
p21 <- ggplot(data = sleepstudy, aes(x = Days, y = Reaction))
p21+ geom_point() + geom_smooth()
p21+ geom_point() + geom_smooth()+ geom_line(aes(y=pred1new1,group = Subject) ,col="red", lwd = 0.5)
不同结果的原因可能是什么?这是由于数据不平衡造成的吗? 我使用的数据是在 3 个时间步中收集的,有些人在所有 3 个时间步中都没有。但是toy数据集是平衡数据集
谢谢
tl;dr 使用 expand.grid()
或类似的东西为每个组生成一个 balanced/evenly 间隔样本(如果你有一个强非线性曲线你可能想要生成一组 larger/more 比原始数据间隔更小的 x 值)
您还可以查看 sjPlot
包,它会自动执行很多此类操作...
您需要不平衡数据集和固定效应的非线性(例如多项式)模型才能看到此效应。
- 如果模型是线性的,那么您不会注意到缺失值,因为
geom_line()
完成的线性插值非常完美 - 如果数据是平衡的,那么就没有间隙可以被线性插值奇怪地填充
生成具有二次效应和不平衡数据集的示例;适合模型
library(lme4)
set.seed(101)
dd <- expand.grid(id=factor(1:10),x=1:10)
dd$y <- simulate(~poly(x,2)+(poly(x,2)|id),
newdata=dd,
family=gaussian,
newparams=list(beta=c(0,0,0.1),
theta=rep(0.1,6),
sigma=1))[[1]]
## subsample randomly (missing values)
dd <- dd[sort(sample(nrow(dd),size=round(0.7*nrow(dd)))),]
m1 <- lmer(y ~ poly(x,2) + (poly(x,2)|id) , data = dd)
天真的预测和情节:
dd$pred1 <- predict(m1,re.form=NA)
library(ggplot2)
p11 <- (ggplot(data = dd, aes(x = x, y = y))
+ geom_point() + geom_smooth(method="lm",formula=y~poly(x,2))
)
p11 + geom_line(aes(y=pred1,group = id) ,col="red", lwd = 0.5)
现在生成一个平衡的数据集。此版本在最小值和最大值之间生成 51 个均匀间隔的点 - 如果原始数据间隔不均匀,这将很有用。如果您的 x
变量中有 NA 值,请不要忘记 na.rm=TRUE
...
pframe <- with(dd,expand.grid(id=levels(id),x=seq(min(x),max(x),length.out=51)
进行预测,并将其叠加在原始图上:
pframe$pred1 <- predict(m1,newdata=pframe,re.form=NA)
p11 + geom_line(data=pframe,aes(y=pred1,group = id) ,col="red", lwd = 0.5)