使用ggplot2仅将一个轴转换为对数刻度

63

我有以下问题:我想在一个箱线图上可视化一个离散变量和一个连续变量,其中后者具有一些极高的值。这使得箱线图没有意义(点甚至是图表的“主体”都太小了),所以我想在log10比例尺上显示它们。我知道我可以从可视化中省略极端值,但我并不打算这样做。

让我们通过钻石数据看一个简单的例子:

m <- ggplot(diamonds, aes(y = price, x = color))

alt text

这里的问题并不严重,但我希望你能想象为什么我想看到对数10刻度上的值。让我们试一试:

m + geom_boxplot() + coord_trans(y = "log10")

alt text

从图中可以看出y轴是以log10为标度的,看起来不错,但是x轴存在问题,这使得绘图非常奇怪。

如果使用scale_log则不会出现问题,但是对于我来说这不是一个选项,因为我不能以这种方式使用自定义格式化程序。例如:

m + geom_boxplot() + scale_y_log10() 

alt text

我的问题是:有没有人知道如何绘制log10比例尺的箱线图,其标签可以自由格式化为像此贴中的formatter函数?


编辑问题以帮助回答者基于答案和评论:

我真正想要的是:一个log10转换轴(y)以非科学标签进行标注。 我想要将其标记为dollar (formatter=dollar)或任何自定义格式。

如果我尝试@hadley的建议,我会收到以下警告:

> m + geom_boxplot() + scale_y_log10(formatter=dollar)
Warning messages:
1: In max(x) : no non-missing arguments to max; returning -Inf
2: In max(x) : no non-missing arguments to max; returning -Inf
3: In max(x) : no non-missing arguments to max; returning -Inf

保持y轴标签不变:

alt text


2
那是coord_trans中的一个错误 - 但你可以指定自定义标签到scale_y_log10... - hadley
谢谢@hadley,我可能错过了什么,但是例如+ scale_y_continous(formatter=dollar)就不起作用。我看不到任何给定格式化程序的结果,而且我还收到了三个In max(x) : no non-missing arguments to max; returning -Inf警告消息。 - daroczig
@daroxzig:我看到的格式化程序参数示例都涉及引号括起来的名称,所以也许可以使用formatter="dollar" - IRTFM
@DWin:我也试过加引号,但结果完全一样。 - daroczig
2
格式化程序还没有工作(但是您仍然可以手动设置标签...) - hadley
@hadley:我也会关注这个(手动/自定义标签)的。现在,看起来数据转换和“scale_y_continuous”格式化程序解决了问题。谢谢! - daroczig
4个回答

49

最简单的方法就是在scale_x_continuousscale_y_continuous的'trans'(以前称为'formatter')参数中指定所需的对数函数名称:

library(ggplot2)  # which formerly required pkg:plyr
m + geom_boxplot() + scale_y_continuous(trans='log10')

编辑: 或者如果您不喜欢那个选项,那么以下任何一个似乎都会给出不同但有用的结果:

m <- ggplot(diamonds, aes(y = price, x = color), log="y")
m + geom_boxplot() 
m <- ggplot(diamonds, aes(y = price, x = color), log10="y")
m + geom_boxplot()

编辑2 & 3: 进一步的实验(排除那个试图在记录的值前成功放置“$”符号的实验后):

# Need a function that accepts an x argument
# wrap desired formatting around numeric result
fmtExpLg10 <- function(x) paste(plyr::round_any(10^x/1000, 0.01) , "K $", sep="")

ggplot(diamonds, aes(color, log10(price))) + 
  geom_boxplot() + 
  scale_y_continuous("Price, log10-scaling", trans = fmtExpLg10)

alt text

2017年中期添加的注释关于包语法变更:

scale_y_continuous(formatter = 'log10') 现在变成了 scale_y_continuous(trans = 'log10') (ggplot2 v2.2.1)


1
@daroczig:使用“美元化”的“成功实验”是 fmtLg10dlr <- function(x) dollar(log10(x)); m + geom_boxplot() + scale_y_continuous(formatter='fmtLg10dlr'),但我觉得它看起来有些不对。 - IRTFM
2
我猜你正在尝试做类似于ggplot(diamonds, aes(color, log10(price))) + geom_boxplot() + scale_y_continuous(formatter = function(x) format(10 ^ x))的事情 - 你需要转换数据并反向转换标签。 - hadley
@daroczig:我这样做了,并添加了我建议的比例标签修复。 - IRTFM
另一个类似的解决方案,使用sprintffmtdol<- function(x)sprintf('$%sK',x/1000) - NiuBiBang
9
scale_y_continuous(formatter = 'log10')现在变成了scale_y_continuous(trans = 'log10')(ggplot2 v2.2.1)。 - pat-s
显示剩余8条评论

19

我遇到了类似的问题,这个比例尺对我非常有用:

breaks = 10**(1:10)
scale_y_log10(breaks = breaks, labels = comma(breaks))

如果你想要中间级别(10^3.5),你需要调整格式:

breaks = 10**(1:10 * 0.5)
m <- ggplot(diamonds, aes(y = price, x = color)) + geom_boxplot()
m + scale_y_log10(breaks = breaks, labels = comma(breaks, digits = 1))
执行后:

输入图像描述


我刚刚注意到这个非常相似的问题有相同的解决方案。 - Susanne Oberhauser
2
感谢您指出这个备选方案,它可以通过指定简单的“dollar”格式化程序或编写自定义格式化程序来完善:+ scale_y_log10(breaks = breaks, labels = dollar(breaks))。谢谢。 - daroczig

10

使用scale_y_log10trans_breakstrans_format以及annotation_logticks()的另一种解决方案。

library(ggplot2)

m <- ggplot(diamonds, aes(y = price, x = color))

m + geom_boxplot() +
  scale_y_log10(
    breaks = scales::trans_breaks("log10", function(x) 10^x),
    labels = scales::trans_format("log10", scales::math_format(10^.x))
  ) +
  theme_bw() +
  annotation_logticks(sides = 'lr') +
  theme(panel.grid.minor = element_blank())


2
非常优美的输出 - Cris
2
2020年,这是第一个复制、粘贴并且能够正常工作的答案。(是的,我尝试了所有方法。)谢谢! - DomQ

2

我认为最后通过在可视化之前对数据进行一些手动转换,我终于搞清楚了:

d <- diamonds
# computing logarithm of prices
d$price <- log10(d$price)

并编写一个格式化程序,以便稍后计算“回溯”对数数据:

formatBack <- function(x) 10^x 
# or with special formatter (here: "dollar")
formatBack <- function(x) paste(round(10^x, 2), "$", sep=' ') 

使用给定的格式绘制图形:

m <- ggplot(d, aes(y = price, x = color))
m + geom_boxplot() + scale_y_continuous(formatter='formatBack')

alt text

很抱歉向社区提出一个我本可以在之前解决的问题!有趣的是:一个月前我曾经努力让这个图表工作,但没有成功。在这里问了之后,我终于得到了答案。

无论如何,感谢@DWin的鼓励!


我认为格式化程序现在已更改为标签 => https://dev59.com/bmkw5IYBdhLWcg3wGGm8 - Bernie2436

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接