如何在ggplot坐标轴标签中使用数学表达式和斜体?
如何在ggplot坐标轴标签中使用数学表达式和斜体?
我太懂这种挫败感了——想把分类轴的标签换成专业的化学符号(带斜体δ和上标),试了好几种方法都没看到效果对吧?其实你之前的思路方向是对的,只是在细节上踩了小坑,我们来一步步把它搞定!
问题出在哪?
你之前尝试修改因子水平的时候,语法用错了:levels(df$x) <- c("d13C" = expression(...), "d15N" = expression(...)) 这种赋值方式并不符合R里因子水平替换的规则。另外,expression(paste(...)) 其实可以简化,不用嵌套paste,直接写表达式就行。
方法一:修改原始数据的因子水平(永久生效)
我们可以直接给因子的每个水平替换成对应的表达式,注意要用正确的赋值语法:
# 先重新生成原始数据(避免之前的错误修改影响) df <- data.frame(x = factor(rep(c("d13C", "d15N"), each = 10)), y = c(rnorm(5, 1, 1), rnorm(5, 2, 1), rnorm(5, 5, 1), rnorm(5, 3, 1)), group = rep(c("a", "b"), each = 5, times = 2)) # 正确替换因子水平:用命名向量指定对应关系 levels(df$x) <- setNames( c(expression(italic(delta)^13*C), expression(italic(delta)^15*N)), c("d13C", "d15N") ) # 绘制图形,现在轴标签会自动生效 ggplot(df, aes(x = x, y = y, col = group)) + geom_rect(aes(xmin = as.numeric(x) - 0.5, xmax = as.numeric(x) + 0.5, ymin = -Inf, ymax = Inf, fill = x), alpha = 0.05) + geom_boxplot() + scale_fill_manual(values = c("green", "purple"))
方法二:不修改原始数据,用scale_x_discrete自定义轴标签(更灵活)
如果你不想改动原始数据,直接在ggplot的刻度设置里指定标签会更灵活,这里有两种写法:
写法1:直接传入表达式列表
# 用原始数据,不修改因子水平 df <- data.frame(x = factor(rep(c("d13C", "d15N"), each = 10)), y = c(rnorm(5, 1, 1), rnorm(5, 2, 1), rnorm(5, 5, 1), rnorm(5, 3, 1)), group = rep(c("a", "b"), each = 5, times = 2)) ggplot(df, aes(x = x, y = y, col = group)) + geom_rect(aes(xmin = as.numeric(x) - 0.5, xmax = as.numeric(x) + 0.5, ymin = -Inf, ymax = Inf, fill = x), alpha = 0.05) + geom_boxplot() + scale_fill_manual(values = c("green", "purple")) + # 重点:用scale_x_discrete指定标签为表达式 scale_x_discrete(labels = c( "d13C" = expression(italic(delta)^13*C), "d15N" = expression(italic(delta)^15*N) ))
写法2:用字符串+parse=TRUE(更简洁)
如果你觉得写expression太繁琐,也可以用带语法的字符串,然后开启解析:
ggplot(df, aes(x = x, y = y, col = group)) + geom_rect(aes(xmin = as.numeric(x) - 0.5, xmax = as.numeric(x) + 0.5, ymin = -Inf, ymax = Inf, fill = x), alpha = 0.05) + geom_boxplot() + scale_fill_manual(values = c("green", "purple")) + scale_x_discrete( labels = c( "d13C" = "italic(delta)^13*C", "d15N" = "italic(delta)^15*N" ), parse = TRUE # 开启字符串解析为表达式 )
为什么你的geom_rect依然有效?
不用担心修改轴标签后,as.numeric(x) 会失效——因为因子被数值化时,是按照它的水平顺序来的,不管标签改成什么表达式,数值化的结果还是1、2,所以你的背景矩形依然能正确对应每个分类的位置。




