ggplot2轴标签中的SI前缀

时间:2012-12-20 13:50:41

标签: r ggplot2

我经常在GNU R / ggplot中绘制图形,用于与字节相关的一些测量。内置轴标签是普通数字或科学记数法,即1兆字节= 1e6。我想要SI前缀(Kilo = 1e3,Mega = 1e6,Giga = 1e9等),即轴应标记为1.5K,5K,1M,150M,4G等。

我目前使用以下代码:

si_num <- function (x) {

  if (!is.na(x)) {
    if (x > 1e6) { 
      chrs <- strsplit(format(x, scientific=12), split="")[[1]];
      rem <- chrs[seq(1,length(chrs)-6)];
      rem <- append(rem, "M");
    }

    else if (x > 1e3) { 
      chrs <- strsplit(format(x, scientific=12), split="")[[1]];
      rem <- chrs[seq(1,length(chrs)-3)];
      rem <- append(rem, "K");
    }
    else {
      return(x);
    }

    return(paste(rem, sep="", collapse=""));
  }
  else return(NA);
} 

si_vec <- function(x) {
  sapply(x, FUN=si_num);
}

library("ggplot2");

bytes=2^seq(0,20) + rnorm(21, 4, 2);
time=bytes/(1e4 + rnorm(21, 100, 3)) + 8;

my_data = data.frame(time, bytes);

p <- ggplot(data=my_data, aes(x=bytes, y=time)) +
     geom_point() +
     geom_line() +
     scale_x_log10("Message Size [Byte]", labels=si_vec) +
     scale_y_continuous("Round-Trip-Time [us]");
p;

我想知道这个解决方案是否可以改进,因为我的每个图形都需要很多样板代码。

2 个答案:

答案 0 :(得分:24)

我使用library("sos"); findFn("{SI prefix}")查找sitools包。

构建数据:

bytes <- 2^seq(0,20) + rnorm(21, 4, 2)
time <- bytes/(1e4 + rnorm(21, 100, 3)) + 8
my_data <- data.frame(time, bytes)

加载套餐:

library("sitools")
library("ggplot2")    

创建情节:

(p <- ggplot(data=my_data, aes(x=bytes, y=time)) +
     geom_point() +
     geom_line() +
     scale_x_log10("Message Size [Byte]", labels=f2si) +
     scale_y_continuous("Round-Trip-Time [us]"))

我不确定这与你的功能相比如何,但至少有其他人去编写它的麻烦......

我稍微修改了你的代码风格 - 行末端的分号是无害的,但通常是MATLAB或C编码器的标志......

编辑:我最初定义了一个通用的格式化函数

si_format <- function(...) {
    function(x) f2si(x,...)
}

遵循(例如)scales::comma_format的格式,但在这种情况下似乎没有必要 - 只是我不完全理解的更深层ggplot2魔法的一部分。

OP的代码给出了我认为不正确的答案:最右边的轴刻度是“1000K”而不是“1M” - 这可以通过将>1e6测试更改为{{}来解决1}}。另一方面,>=1e6使用小写f2si - 我不知道是否需要k(将结果包装在K中可以解决此问题。)< / p>

OP结果(toupper()):

enter image description here

我的结果(si_vec):

enter image description here

答案 1 :(得分:0)

字节为gdata::humanReadablehumanReadable支持SI前缀(1000字节= 1 KB)和binary prefixes defined by the IEC(1024字节= 1 KiB)。

此功能humanReadableLabs允许自定义参数并处理NA值:

humanReadableLabs <- function(units="auto", standard="IEC", digits=1, width=NULL, sep=" ", justify="right") {
    function(x) {
        sapply(x, function(val) {
            if (is.na(val)) {
                return("")
            } else {
                return(
                    humanReadable(val, units=units, standard=standard, digits=digits, width=width, sep=sep, justify=justify)
                )
            }
        })
    }
}

现在可以很容易地更改标签以使用SI前缀和“字节”作为单位:

library(ggplot2)
library(gdata)

bytes <- 2^seq(0,20) + rnorm(21, 4, 2)

my_data <- data.frame(
    bytes=as.integer(bytes),
    time=bytes / (1e4 + rnorm(21, 100, 3)) + 8
)

humanReadableLabs <- function(...) {...}

ggplot(data=my_data, aes(x=bytes, y=time)) +
    geom_point() +
    geom_line() +
    scale_x_log10("Message Size [Byte]", labels=humanReadableLabs(standard="SI")) +
    scale_y_continuous("Round-Trip-Time [us]")

si-labels

IEC前缀通过省略standard="SI"来绘制。请注意,还必须指定休息时间以使其值清晰易懂。

ggplot(data=my_data, aes(x=bytes, y=time)) +
    geom_point() +
    geom_line() +
    scale_x_log10("Message Size [Byte]", labels=humanReadableLabs()) +
    scale_y_continuous("Round-Trip-Time [us]")

iec-labels