16

バイトに関連するいくつかの測定値について、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;

私のソリューションではすべてのグラフに多くの定型コードが必要なため、このソリューションを改善できるかどうかを知りたいと思います。

4

2 に答える 2

29

私はパッケージ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,...)
}

(eg)の形式に従いますがscales::comma_format、この場合は不要のようggplot2です。私が完全には理解していない、より深い魔法の一部にすぎません。

OPのコードは、私には完全に正しい答えではないように思われるものを示しています。右端の軸の目盛りは「1M」ではなく「1000K」です。これは、>1e6テストをに変更することで修正できます>=1e6。一方、f2si小文字を使用しますk-必要かどうかはわかりませんK(結果をラップするとtoupper()これを修正できます)。

OP結果(si_vec):

ここに画像の説明を入力してください

私の結果(f2si):

ここに画像の説明を入力してください

于 2012-12-20T14:51:48.863 に答える
5

更新:パッケージの最近のバージョンには、scales読み取り可能なラベルを印刷する機能が含まれています。

この場合、label_bytes次を使用できます。

library(ggplot2)
library(scales)

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
)

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

scales-si-labels

または、IEC単位(、、KiB = 2^10... MiB = 2 ^ 20)を使用する場合は、を指定しますlabels=label_bytes(units = "auto_binary")。結果は非常に似ているため、以下の元の回答の2番目のプロットを確認してください。


元の回答

バイトには。がありgdata::humanReadableます。humanReadableSIプレフィックス(1000バイト= 1 KB)とIECで定義されたバイナリプレフィックス(1024バイト= 1 KiB)の両方をサポートします。

この関数humanReadableLabsを使用すると、パラメーターをカスタマイズして値を処理できNAます。

humanReadableLabs <- function(...) {
    function(x) {
        sapply(x, function(val) {
            if (is.na(val)) {
                return("")
            } else {
                return(
                    humanReadable(val, ...)
                )
            }
        })
    }
}

これで、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-ラベル

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

于 2019-12-16T19:28:09.800 に答える