我们能否巧妙地将回归方程与 R2 和 p 值对齐?
Can we neatly align the regression equation and R2 and p value?
将回归方程、R2 和 p 值(对于方程)巧妙地添加到 ggplot 图中的最佳(最简单)方法是什么?理想情况下,它应该与组和分面兼容。
第一个图有回归方程加上 r2 和 p 值,使用 ggpubr,但它们没有对齐?我错过了什么吗?它们可以作为一个字符串包含在内吗?
library(ggplot)
library(ggpubr)
ggplot(mtcars, aes(x = wt, y = mpg, group = cyl))+
geom_smooth(method="lm")+
geom_point()+
stat_regline_equation()+
stat_cor(aes(label = paste(..rr.label.., ..p.label.., sep = "*`,`~")),
label.x.npc = "centre")
这是一个带有 ggpmisc 的选项,它做了一些奇怪的放置。
EDIT 奇怪的位置是由 geom=text
引起的,我已经注释掉它以提供更好的位置,并添加了 `label.x = "right" 以停止过度绘制.由于@dc37
标记的上标问题,根据 ggpubr,我们仍然有错位
#
library(ggpmisc)
ggplot(mtcars, aes(x = wt, y = mpg, group = cyl))+
geom_smooth(method="lm")+
geom_point()+
stat_poly_eq(formula = "y~x",
aes(label = paste(..eq.label.., ..rr.label.., sep = "*`,`~")),
parse = TRUE)+
stat_fit_glance(method = 'lm',
method.args = list(formula = "y~x"),
#geom = 'text',
aes(label = paste("P-value = ", signif(..p.value.., digits = 4), sep = "")))
我确实找到了一个很好的解决方案,可以将相关的统计数据放在一起,但这需要在 ggplot 之外创建回归,以及一堆字符串操作问题 - 这真的很简单吗?此外,它不(按照当前编码)处理分组,也不会处理分面。
#
#Solution as one string, equation, R2 and p-value
lm_eqn <- function(df, y, x){
formula = as.formula(sprintf('%s ~ %s', y, x))
m <- lm(formula, data=df);
# formating the values into a summary string to print out
# ~ give some space, but equal size and comma need to be quoted
eq <- substitute(italic(target) == a + b %.% italic(input)*","~~italic(r)^2~"="~r2*","~~p~"="~italic(pvalue),
list(target = y,
input = x,
a = format(as.vector(coef(m)[1]), digits = 2),
b = format(as.vector(coef(m)[2]), digits = 2),
r2 = format(summary(m)$r.squared, digits = 3),
# getting the pvalue is painful
pvalue = format(summary(m)$coefficients[2,'Pr(>|t|)'], digits=1)
)
)
as.character(as.expression(eq));
}
ggplot(mtcars, aes(x = wt, y = mpg, group=cyl))+
geom_point() +
geom_text(x=3,y=30,label=lm_eqn(mtcars, 'wt','mpg'),color='red',parse=T) +
geom_smooth(method='lm')
ggpubr
的一个可能解决方案是通过将 Inf
传递给 label.y
和 Inf
或 [= 将方程式和 R2 值放在图表的顶部17=] 到 label.x
(取决于你是想把它放在图的右边还是左边)
由于 R 上的上标 2,两个文本都不会对齐。因此,您必须使用 vjust
和 hjust
稍微调整一下,以便对齐两个文本。
然后,它甚至可以处理不同比例的多面图。
library(ggplot)
library(ggpubr)
ggplot(mtcars, aes(x = wt, y = mpg, group = cyl))+
geom_smooth(method="lm")+
geom_point()+
stat_regline_equation(label.x = -Inf, label.y = Inf, vjust = 1.5, hjust = -0.1, size = 3)+
stat_cor(aes(label = paste(..rr.label.., ..p.label.., sep = "*`,`~")),
label.y= Inf, label.x = Inf, vjust = 1, hjust = 1.1, size = 3)+
facet_wrap(~cyl, scales = "free")
它能回答您的问题吗?
编辑:通过手动添加等式替代
如您的类似问题 () 中所述,您可以通过将文本作为 geom_text
:
传递来添加方程式
df_mtcars <- mtcars %>% mutate(factor_cyl = as.factor(cyl))
df_label <- df_mtcars %>% group_by(factor_cyl) %>%
summarise(Inter = lm(mpg~wt)$coefficients[1],
Coeff = lm(mpg~wt)$coefficients[2],
pval = summary(lm(mpg~wt))$coefficients[2,4],
r2 = summary(lm(mpg~wt))$r.squared) %>% ungroup() %>%
#mutate(ypos = max(df_mtcars$mpg)*(1-0.05*row_number())) %>%
#mutate(Label2 = paste(factor_cyl,"~Cylinders:~", "italic(y)==",round(Inter,3),ifelse(Coeff <0,"-","+"),round(abs(Coeff),3),"~italic(x)",sep ="")) %>%
mutate(Label = paste("italic(y)==",round(Inter,3),ifelse(Coeff <0,"-","+"),round(abs(Coeff),3),"~italic(x)",
"~~~~italic(R^2)==",round(r2,3),"~~italic(p)==",round(pval,3),sep =""))
# A tibble: 3 x 6
factor_cyl Inter Coeff pval r2 Label
<fct> <dbl> <dbl> <dbl> <dbl> <chr>
1 4 39.6 -5.65 0.0137 0.509 italic(y)==39.571-5.647~italic(x)~~~~italic(R^2)==0.509~~italic(p)==0.014
2 6 28.4 -2.78 0.0918 0.465 italic(y)==28.409-2.78~italic(x)~~~~italic(R^2)==0.465~~italic(p)==0.092
3 8 23.9 -2.19 0.0118 0.423 italic(y)==23.868-2.192~italic(x)~~~~italic(R^2)==0.423~~italic(p)==0.012
您可以将其用于 geom_text
,如下所示:
ggplot(df_mtcars,aes(x = wt, y = mpg, group = factor_cyl, colour= factor_cyl))+
geom_smooth(method="lm")+
geom_point()+
geom_text(data = df_label,
aes(x = -Inf, y = Inf,
label = Label, color = factor_cyl),
show.legend = FALSE, parse = TRUE, size = 3,vjust = 1, hjust = 0)+
facet_wrap(~factor_cyl)
至少解决了R上标2导致的错位问题
这里我使用 ggpmisc,一次调用 stat_poly_eq()
得到方程(中间顶部),一次调用 stat_fit_glance()
得到统计数据(pvalue 和 r2)。对齐的秘诀是使用 yhat 作为等式的左侧,因为帽子近似于文本高度,然后匹配 r2 的上标 - yhat 的帽子尖到 Pedro Aphalo,显示 here。
将它们作为一个字符串会很棒,这意味着水平对齐不会成为问题,然后将其方便地定位在绘图 space 中会更容易。我已在 ggpubr and ggpmisc.
提出问题
我很乐意接受另一个更好的答案!
library(ggpmisc)
df_mtcars <- mtcars %>% mutate(factor_cyl = as.factor(cyl))
my_formula <- "y~x"
ggplot(df_mtcars, aes(x = wt, y = mpg, group = factor_cyl, colour= factor_cyl))+
geom_smooth(method="lm")+
geom_point()+
stat_poly_eq(formula = my_formula,
label.x = "centre",
eq.with.lhs = "italic(hat(y))~`=`~",
aes(label = paste(..eq.label.., sep = "~~~")),
parse = TRUE)+
stat_fit_glance(method = 'lm',
method.args = list(formula = my_formula),
#geom = 'text',
label.x = "right", #added to prevent overplotting
aes(label = paste("~italic(p) ==", round(..p.value.., digits = 3),
"~italic(R)^2 ==", round(..r.squared.., digits = 2),
sep = "~")),
parse=TRUE)+
theme_minimal()
注意 facet 也能很好地工作,你可以为 facet 和分组设置不同的变量,一切仍然有效。
注意:如果您确实为组和面使用相同的变量,则在每次调用中添加 label.y= Inf,
将强制标签位于每个面的顶部(帽子提示@dc37,在另一个答案中问题)。
我已更新 'ggpmisc' 以简化此操作。 0.3.4 版本正在向 CRAN 发送,源码包已上线,二进制文件应该会在几天内构建。
library(ggpmisc) # version >= 0.3.4 !!
ggplot(mtcars, aes(x = wt, y = mpg, group = cyl)) +
geom_smooth(method="lm")+
geom_point()+
stat_poly_eq(formula = y ~ x,
aes(label = paste(..eq.label.., ..rr.label.., ..p.value.label.., sep = "*`,`~")),
parse = TRUE,
label.x.npc = "right",
vstep = 0.05) # sets vertical spacing
将回归方程、R2 和 p 值(对于方程)巧妙地添加到 ggplot 图中的最佳(最简单)方法是什么?理想情况下,它应该与组和分面兼容。
第一个图有回归方程加上 r2 和 p 值,使用 ggpubr,但它们没有对齐?我错过了什么吗?它们可以作为一个字符串包含在内吗?
library(ggplot)
library(ggpubr)
ggplot(mtcars, aes(x = wt, y = mpg, group = cyl))+
geom_smooth(method="lm")+
geom_point()+
stat_regline_equation()+
stat_cor(aes(label = paste(..rr.label.., ..p.label.., sep = "*`,`~")),
label.x.npc = "centre")
这是一个带有 ggpmisc 的选项,它做了一些奇怪的放置。
EDIT 奇怪的位置是由 geom=text
引起的,我已经注释掉它以提供更好的位置,并添加了 `label.x = "right" 以停止过度绘制.由于@dc37
#
library(ggpmisc)
ggplot(mtcars, aes(x = wt, y = mpg, group = cyl))+
geom_smooth(method="lm")+
geom_point()+
stat_poly_eq(formula = "y~x",
aes(label = paste(..eq.label.., ..rr.label.., sep = "*`,`~")),
parse = TRUE)+
stat_fit_glance(method = 'lm',
method.args = list(formula = "y~x"),
#geom = 'text',
aes(label = paste("P-value = ", signif(..p.value.., digits = 4), sep = "")))
我确实找到了一个很好的解决方案,可以将相关的统计数据放在一起,但这需要在 ggplot 之外创建回归,以及一堆字符串操作问题 - 这真的很简单吗?此外,它不(按照当前编码)处理分组,也不会处理分面。
#
#Solution as one string, equation, R2 and p-value
lm_eqn <- function(df, y, x){
formula = as.formula(sprintf('%s ~ %s', y, x))
m <- lm(formula, data=df);
# formating the values into a summary string to print out
# ~ give some space, but equal size and comma need to be quoted
eq <- substitute(italic(target) == a + b %.% italic(input)*","~~italic(r)^2~"="~r2*","~~p~"="~italic(pvalue),
list(target = y,
input = x,
a = format(as.vector(coef(m)[1]), digits = 2),
b = format(as.vector(coef(m)[2]), digits = 2),
r2 = format(summary(m)$r.squared, digits = 3),
# getting the pvalue is painful
pvalue = format(summary(m)$coefficients[2,'Pr(>|t|)'], digits=1)
)
)
as.character(as.expression(eq));
}
ggplot(mtcars, aes(x = wt, y = mpg, group=cyl))+
geom_point() +
geom_text(x=3,y=30,label=lm_eqn(mtcars, 'wt','mpg'),color='red',parse=T) +
geom_smooth(method='lm')
ggpubr
的一个可能解决方案是通过将 Inf
传递给 label.y
和 Inf
或 [= 将方程式和 R2 值放在图表的顶部17=] 到 label.x
(取决于你是想把它放在图的右边还是左边)
由于 R 上的上标 2,两个文本都不会对齐。因此,您必须使用 vjust
和 hjust
稍微调整一下,以便对齐两个文本。
然后,它甚至可以处理不同比例的多面图。
library(ggplot)
library(ggpubr)
ggplot(mtcars, aes(x = wt, y = mpg, group = cyl))+
geom_smooth(method="lm")+
geom_point()+
stat_regline_equation(label.x = -Inf, label.y = Inf, vjust = 1.5, hjust = -0.1, size = 3)+
stat_cor(aes(label = paste(..rr.label.., ..p.label.., sep = "*`,`~")),
label.y= Inf, label.x = Inf, vjust = 1, hjust = 1.1, size = 3)+
facet_wrap(~cyl, scales = "free")
它能回答您的问题吗?
编辑:通过手动添加等式替代
如您的类似问题 (geom_text
:
df_mtcars <- mtcars %>% mutate(factor_cyl = as.factor(cyl))
df_label <- df_mtcars %>% group_by(factor_cyl) %>%
summarise(Inter = lm(mpg~wt)$coefficients[1],
Coeff = lm(mpg~wt)$coefficients[2],
pval = summary(lm(mpg~wt))$coefficients[2,4],
r2 = summary(lm(mpg~wt))$r.squared) %>% ungroup() %>%
#mutate(ypos = max(df_mtcars$mpg)*(1-0.05*row_number())) %>%
#mutate(Label2 = paste(factor_cyl,"~Cylinders:~", "italic(y)==",round(Inter,3),ifelse(Coeff <0,"-","+"),round(abs(Coeff),3),"~italic(x)",sep ="")) %>%
mutate(Label = paste("italic(y)==",round(Inter,3),ifelse(Coeff <0,"-","+"),round(abs(Coeff),3),"~italic(x)",
"~~~~italic(R^2)==",round(r2,3),"~~italic(p)==",round(pval,3),sep =""))
# A tibble: 3 x 6
factor_cyl Inter Coeff pval r2 Label
<fct> <dbl> <dbl> <dbl> <dbl> <chr>
1 4 39.6 -5.65 0.0137 0.509 italic(y)==39.571-5.647~italic(x)~~~~italic(R^2)==0.509~~italic(p)==0.014
2 6 28.4 -2.78 0.0918 0.465 italic(y)==28.409-2.78~italic(x)~~~~italic(R^2)==0.465~~italic(p)==0.092
3 8 23.9 -2.19 0.0118 0.423 italic(y)==23.868-2.192~italic(x)~~~~italic(R^2)==0.423~~italic(p)==0.012
您可以将其用于 geom_text
,如下所示:
ggplot(df_mtcars,aes(x = wt, y = mpg, group = factor_cyl, colour= factor_cyl))+
geom_smooth(method="lm")+
geom_point()+
geom_text(data = df_label,
aes(x = -Inf, y = Inf,
label = Label, color = factor_cyl),
show.legend = FALSE, parse = TRUE, size = 3,vjust = 1, hjust = 0)+
facet_wrap(~factor_cyl)
至少解决了R上标2导致的错位问题
这里我使用 ggpmisc,一次调用 stat_poly_eq()
得到方程(中间顶部),一次调用 stat_fit_glance()
得到统计数据(pvalue 和 r2)。对齐的秘诀是使用 yhat 作为等式的左侧,因为帽子近似于文本高度,然后匹配 r2 的上标 - yhat 的帽子尖到 Pedro Aphalo,显示 here。
将它们作为一个字符串会很棒,这意味着水平对齐不会成为问题,然后将其方便地定位在绘图 space 中会更容易。我已在 ggpubr and ggpmisc.
提出问题我很乐意接受另一个更好的答案!
library(ggpmisc)
df_mtcars <- mtcars %>% mutate(factor_cyl = as.factor(cyl))
my_formula <- "y~x"
ggplot(df_mtcars, aes(x = wt, y = mpg, group = factor_cyl, colour= factor_cyl))+
geom_smooth(method="lm")+
geom_point()+
stat_poly_eq(formula = my_formula,
label.x = "centre",
eq.with.lhs = "italic(hat(y))~`=`~",
aes(label = paste(..eq.label.., sep = "~~~")),
parse = TRUE)+
stat_fit_glance(method = 'lm',
method.args = list(formula = my_formula),
#geom = 'text',
label.x = "right", #added to prevent overplotting
aes(label = paste("~italic(p) ==", round(..p.value.., digits = 3),
"~italic(R)^2 ==", round(..r.squared.., digits = 2),
sep = "~")),
parse=TRUE)+
theme_minimal()
注意 facet 也能很好地工作,你可以为 facet 和分组设置不同的变量,一切仍然有效。
注意:如果您确实为组和面使用相同的变量,则在每次调用中添加 label.y= Inf,
将强制标签位于每个面的顶部(帽子提示@dc37,在另一个答案中问题)。
我已更新 'ggpmisc' 以简化此操作。 0.3.4 版本正在向 CRAN 发送,源码包已上线,二进制文件应该会在几天内构建。
library(ggpmisc) # version >= 0.3.4 !!
ggplot(mtcars, aes(x = wt, y = mpg, group = cyl)) +
geom_smooth(method="lm")+
geom_point()+
stat_poly_eq(formula = y ~ x,
aes(label = paste(..eq.label.., ..rr.label.., ..p.value.label.., sep = "*`,`~")),
parse = TRUE,
label.x.npc = "right",
vstep = 0.05) # sets vertical spacing