[英]How can one (easier) create nice x-axis ticks (i.e. pi/2, pi, 3pi/2, ...) in ggplot2?
I would like to create a plot, where one can see an alternative ticking of the x-axis, eg pi/2, pi, 3pi/2, etc. So far, this works for me only with a rather unhandy code (look at the lines where I create pi.halfs
, pi.fulls
and merge them later into vec.expr
):我想创建一个图,在那里人们可以看到 x 轴的替代刻度,例如 pi/2、pi、3pi/2 等。到目前为止,这仅适用于我的一个相当不方便的代码(看看我创建
pi.halfs
、 pi.fulls
并稍后将它们合并到vec.expr
):
require (ggplot2)
# Create vectors: breaks and corresponding labels as multiples of pi/2
vec.breaks <- seq(from = pi/2, to = 7*pi/2, by = pi/2)
pi.halfs <- c(paste(expression(pi), "/2"),
paste(seq(from = 3, to = 21, by = 2), "*" , expression(pi), "/2"))
pi.fulls <- c(paste(expression(pi)),
paste(seq(from = 2, to = 11, by = 1), "*" , expression(pi)))
vec.expr <- parse(text = c(rbind(pi.halfs, pi.fulls)))[1:7]
# Create some time and signal
time <- seq(from = 0, to = 4*pi, by = 0.01)
signal <- sin(time)
df <- data.frame(time,signal)
# Now plot the signal with the new x axis labels
fig <- ggplot(data = df, aes(x = time, y = signal)) +
geom_line() +
scale_x_continuous(breaks=vec.breaks, labels=vec.expr)
print(fig)
... resulting in ... ... 导致 ...
Is anyone aware of an easier approach, where one can change the base of some x-axis labeling in ggplot2, eg like here from decimals to multiples of pi?有没有人知道一种更简单的方法,可以在 ggplot2 中更改某些 x 轴标签的基数,例如这里从小数到 pi 的倍数? Are there any nice packages, that I missed so far?
有没有什么好的包,我到目前为止错过了? I found some duplicates of this question, but only in other languages...
我发现了这个问题的一些重复,但仅限于其他语言......
You are looking for the scales package, which lets you create arbitrary formatting functions for scales and also has a number of helpful formatting functions already built in. Looking through the scales package help, I was surprised not to find a radian scale, but you should be able to create one using math_formatter()
.您正在寻找scales包,它允许您为比例创建任意格式化函数,并且还内置了许多有用的格式化函数。查看 scales 包帮助,我很惊讶没有找到弧度比例,但您应该能够使用
math_formatter()
创建一个。 This code gets the same results, though not with the fractions.这段代码得到相同的结果,但不是分数。
library(ggplot2)
library(scales)
time <- seq(from = 0, to = 4*pi, by = 0.01)
signal <- sin(time)
df <- data.frame(time,signal)
pi_scales <- math_format(.x * pi, format = function(x) x / pi)
fig <- ggplot(data = df, aes(x = time, y = signal)) +
geom_line() +
scale_x_continuous(labels = pi_scales, breaks = seq(pi / 2, 7 * pi / 2, pi / 2))
print(fig)
Here is a function to make fractional labels (maybe a little clunky).这是一个制作分数标签的函数(可能有点笨重)。 It uses
fractions
from MASS
package and allows you to change the multiplier you want to use on the x-axis.它使用
MASS
包中的fractions
,并允许您更改要在 x 轴上使用的乘数。 You just pass it a symbol (ie. "pi").您只需向它传递一个符号(即“pi”)。 If the symbol has a value, the ticks will be scaled by width*value, otherwise just by width.
如果符号有值,刻度将按宽度*值缩放,否则仅按宽度缩放。
# Now plot the signal with the new x axis labels
p <- ggplot(data = df, aes(x = time, y = signal)) +
geom_line()
## Convert x-ticks to fractional x-ticks with a symbol multiplier
fracAx <- function(p, symbol, width=0.5) {
require(MASS) # for fractions
val <- tryCatch(eval(parse(text=symbol)), error=function(e) 1)
info <- ggplot_build(p)
xrange <- info[[2]]$ranges[[1]]$x.range/val # get the x-range of figure
vec.breaks <- seq(floor(xrange[1]), ceiling(xrange[2]), by=width)
fracs <- strsplit(attr(fractions(vec.breaks), "fracs"), "/") # convert to fractions
labels <- sapply(fracs, function(i)
if (length(i) > 1) { paste(i[1], "*", symbol, "/", i[2]) }
else { paste(i, "*", symbol) })
p + scale_x_continuous(breaks=vec.breaks*val, labels=parse(text=labels))
}
## Make the graph with pi axis
fracAx(p, "pi")
## Make the graph with e axis, for example
e <- exp(1)
fracAx(p, "e")
## Make the graph with a symbol that has no value
fracAx(p, "theta", width=2)
Based on the other answers here I was able to piece together some functions which implement a general radians
format that can be used independently of mucking about with the internals of ggplot2
objects.基于这里的其他答案,我能够将一些实现通用
radians
格式的函数拼凑在一起,这些函数可以独立使用而ggplot2
对象的内部ggplot2
。
numerator <- function(x) {
f = attr(x, "fracs")
s <- as.integer(sign(x))
ifelse(is.finite(x), as.integer(stringr::str_extract(f, "^[^/]*")), s)
}
denominator <- function(x) {
f = attr(x, "fracs")
s <- as.integer(sign(x))
ratio <- str_detect(f, "/")
d <- as.integer(stringr::str_extract(f, "[^/]*$"))
ifelse(is.finite(x), ifelse(ratio, d, 1L), 0L)
}
char_sign <- function(x) {
s <- sign(x)
ifelse(s == 1, "+",
ifelse(s == -1, "-", ""))
}
#' Convert value to radians formatting
radians <- function(x) {
y = x/pi
f = suppressWarnings(MASS::as.fractions(y))
n = suppressWarnings(numerator(f))
d = suppressWarnings(denominator(f))
s <- char_sign(x)
o <- vector(mode = "character", length = length(x))
o <- ifelse(d == 0 & n != 0, paste0(s, "∞"), o)
o <- ifelse(n == 0 & d != 0, "0", o)
o <- ifelse(n != 0 & d != 0, paste0(n, "π/", d), o)
o <- ifelse(n == 1 & d != 0, paste0("π/", d), o)
o <- ifelse(n == -1 & d == 1, paste0(s, "π"), o)
o <- ifelse(n == -1 & d != 0 & d != 1, paste0(s, "π/", d), o)
o <- ifelse(d == 1 & n != 0 & abs(n) != 1, paste0(n, "π"), o)
o <- ifelse(n == d & is.finite(n), "π", o)
o
}
Here it is in use:这里正在使用:
```r
time <- seq(from = 0, to = 4*pi, by = 0.01)
signal <- sin(time)
df <- data.frame(time,signal)
ggplot(df, aes(time, signal)) +
geom_line() +
scale_x_continuous(labels = trans_format(radians, force),
breaks = seq(0, 4*pi, pi/2))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.