You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

R语言axis函数在mgp[3]为非整数值时行为异常的技术问询

R's axis() Function: Unexpected Label Placement When mgp[3] Is Non-Integer

Great question—this is one of those subtle R graphics quirks that the documentation doesn't fully spell out. Let's unpack what's happening with the mgp parameter in axis().

First, let's recap the official documentation:

From ?par: The mgp[1:3] vector specifies the margin lines (in mex units) for axis titles, axis labels, and axis lines. mgp[1] affects the title, while mgp[2:3] affect the axis itself, with a default of c(3, 1, 0). The ?axis documentation echoes this, stating mgp[2] controls label position and mgp[3] controls the axis line position.

But as you've discovered, this only holds true when mgp[3] is an integer. When mgp[3] has a fractional component, the axis line still lands exactly where specified, but the axis labels get shifted to mgp[2] + (mgp[3] %% 1)—a detail completely missing from the docs.

Your example perfectly illustrates this discrepancy:

par(mar = c(5, 1, 5, 1))
plot.new()
plot.window(xlim = c(0, 1), ylim = c(0, 1))
box(lty = 3)

# Integer mgp[3]: labels and axis line match documented positions
mgp_bottom <- c(0, 2.5, 1) # mgp[1] value doesn't affect labels/axis here
axis(side = 1, mgp = mgp_bottom)
mtext(c("labels", "line"), side = 1, line = mgp_bottom[2:3])

# Non-integer mgp[3]: axis line is correct, labels are offset
mgp_top <- mgp_bottom - c(0, 0, 1e-3)
axis(side = 3, mgp = mgp_top)
mtext(c("labels", "line"), side = 3, line = mgp_top[2:3])
mtext("LABELS", side = 3, line = mgp_top[2] + (mgp_top[3] %% 1))

Is this a bug or an undocumented feature?

This is almost certainly an undocumented implementation detail rather than a bug. Digging into the base graphics C code for axis(), the label position calculation combines the fractional part of mgp[3] with mgp[2]—likely as a way to let users fine-tune label placement relative to an axis that's placed on a non-integer margin line. Since this behavior wasn't added to the documentation, it's easy to miss.

Key Takeaways

  • When mgp[3] is an integer: axis() behaves exactly as documented.
  • When mgp[3] is non-integer: Labels shift to mgp[2] + (mgp[3] %% 1), while the axis line stays at mgp[3].

If you need precise control over label position regardless of mgp[3], use your manual calculation method (as shown in the example) or place labels independently with mtext().

内容的提问来源于stack exchange,提问作者Mikael Jagan

火山引擎 最新活动