13

標準の単位プレフィックス(Kilo、Megaなど)を使用して数値(整数)をフォーマットできるR関数(または任意のパッケージ)はありますか?

10 -> 10
1000 -> 1K
0.01 - > 10m

など...私は自分でそれを行うことができますが、私は車輪の再発明をしたくないです。

4

5 に答える 5

17
require(sitools)
f2si(80000)
 [1] "80 k"
f2si(8E12)
 [1] "8 T"

SIプレフィックスが使用されていない場合、2つのスペースが追加されるため、非常に単純なようです。

f2si(80)
[1] "80  "

関数は、丸めを含めるように簡単に変更できます。スペースが追加される問題も修正しました。

f2si2<-function (number,rounding=F) 
{
    lut <- c(1e-24, 1e-21, 1e-18, 1e-15, 1e-12, 1e-09, 1e-06, 
        0.001, 1, 1000, 1e+06, 1e+09, 1e+12, 1e+15, 1e+18, 1e+21, 
        1e+24)
    pre <- c("y", "z", "a", "f", "p", "n", "u", "m", "", "k", 
        "M", "G", "T", "P", "E", "Z", "Y")
    ix <- findInterval(number, lut)
    if (lut[ix]!=1) {
        if (rounding==T) {
         sistring <- paste(round(number/lut[ix]), pre[ix])
        }
        else {
         sistring <- paste(number/lut[ix], pre[ix])
        } 
    }
    else {
        sistring <- as.character(number)
    }
    return(sistring)
}

f2si2(12345)
 [1] "12.345 k"
f2si2(12345,T)
 [1] "12 k"
于 2012-07-05T09:01:23.530 に答える
11

私は同じ質問でここに来ました。ローランドの答えに感謝します。私は彼のコードにいくつかの変更を加えて構築しました:

  • rounding = FALSEの場合に有効数字を指定できます(「signif」組み込み関数と同様に、デフォルトは6です)。
  • 1e-24未満の値でエラーをスローしません
  • 1e27を超える値の科学的記数法(単位なし)を出力します

これがお役に立てば幸いです。

f2si<-function (number, rounding=F, digits=ifelse(rounding, NA, 6)) 
{
    lut <- c(1e-24, 1e-21, 1e-18, 1e-15, 1e-12, 1e-09, 1e-06, 
        0.001, 1, 1000, 1e+06, 1e+09, 1e+12, 1e+15, 1e+18, 1e+21, 
        1e+24, 1e+27)
    pre <- c("y", "z", "a", "f", "p", "n", "u", "m", "", "k", 
        "M", "G", "T", "P", "E", "Z", "Y", NA)
    ix <- findInterval(number, lut)
    if (ix>0 && ix<length(lut) && lut[ix]!=1) {
        if (rounding==T && !is.numeric(digits)) {
            sistring <- paste(round(number/lut[ix]), pre[ix])
        }
        else if (rounding == T || is.numeric(digits)) {
            sistring <- paste(signif(number/lut[ix], digits), pre[ix])
        }
        else {
            sistring <- paste(number/lut[ix], pre[ix])
        } 
    }
    else {
        sistring <- as.character(number)
    }
    return(sistring)
}

f2si(12345)
 [1] "12.345 k"
f2si(12345, T)
 [1] "12 k"
f2si(10^31)
 [1] "1e+31" # (previous version would output "1e+07 Y"
f2si(10^-25)
 [1] "1e-25" # (previous version would throw error)
f2si(123456789)
 [1] "123.457 M" # (previous version would output ""123.456789 M"
f2si(123456789, digits=4)
 [1] "123.5 M" # (note .456 is rounded up to .5)

このコードから、一般的に使用される財務単位(K、MM、Bn、Tr)に対しても同様の関数を作成するのは非常に簡単です。

于 2012-10-26T20:28:32.797 に答える
3

これは、dplyrを使用case_whenしてベクトル化するのが簡単で、目にははるかに簡単です。

library(dplyr)

si_number = function(x, digits) {

    compress = function(x, n) {
        signif(x * 10^(-n), digits)
    }

    case_when(
        x >= 1e6   ~ paste0(compress(x, 6), "M"),
        x >= 1000  ~ paste0(compress(x, 3), "k"),
        x >= 1     ~ as.character(compress(x, 0)),
        x >= 0.001 ~ paste0(compress(x, -3), "m"),
        x >= 1e-6  ~ paste0(compress(x, -6), "u")
    )
}
于 2019-11-28T10:32:26.873 に答える
2

サウザンド(K)、ミリオン(M)、ビリオン(B)の数値変換器を探していました。このルーチンを変更して、必要な出力を吐き出す数値ベクトル/単一の数値を取得しました。

CurrencyFormat <-function (number,rounding=F) 
{
    first <- TRUE
    lut <- c( 1, 1000, 1000000, 1000000000,1000000000000 )
    pre <- c("", "K", "M", "B", "T")
    if (length(number) > 1) {
        for (cnt in 1:length(number)){        
            ix <- findInterval(number[cnt], lut)
            if (ix != 0 | ix != 1){
                if (rounding==T) {
                    sistring <- paste(round(number[cnt]/lut[ix]), pre[ix])
                }
                else {
                    sistring <- paste(signif(number[cnt]/lut[ix],digits=5), pre[ix])
                }
                if (first){
                    tnumber <- sistring
                    fnumber <- tnumber
                    first <- FALSE
                }
                else
                    fnumber <- append(fnumber, sistring)
            }
            else {
                sistring <- number[cnt]
                if (first){
                    tnumber <- sistring
                    fnumber <- tnumber
                    first <- FALSE
                }
                else
                    fnumber <- append(fnumber, sistring)
            }
        }
        return(fnumber)
    }
    else{
        ix <- findInterval(number, lut)
        if (ix != 0 | ix != 1){
            if (rounding==T) {
                sistring <- paste(round(number/lut[ix]), pre[ix])
            }
            else {
                sistring <- paste(signif(number/lut[ix],digits=5), pre[ix])
            }
            return(sistring)
        }    
        else
            return(number)
    }
}

例:

CurrencyFormat(1.25,F)
[1] "1.25 "

CurrencyFormat(1000.25,F)
[1] "1.0002 K"

CurrencyFormat(c( 1,45,1234, 4.36e+06, 2.84e+04, 2.01e+06),F)
[1] "1 "      "45 "     "1.234 K" "4.36 M"  "28.4 K"  "2.01 M" 
于 2015-04-29T00:21:34.780 に答える
1

負の数を考慮してわずかに変更されたバージョン:

f2si<-function (number, rounding=F, digits=ifelse(rounding, NA, 6)) 
{
mysign <- ""
if (number<0) {
    mysign <- "-"
}
number <- abs(number)
lut <- c(1e-24, 1e-21, 1e-18, 1e-15, 1e-12, 1e-09, 1e-06, 
    0.001, 1, 1000, 1e+06, 1e+09, 1e+12, 1e+15, 1e+18, 1e+21, 
    1e+24, 1e+27)
pre <- c("y", "z", "a", "f", "p", "n", "u", "m", "", "k", 
    "M", "G", "T", "P", "E", "Z", "Y", NA)
ix <- findInterval(number, lut)
if (ix>0 && ix<length(lut) && lut[ix]!=1) {
    if (rounding==T && !is.numeric(digits)) {
        sistring <- paste(mysign,mysign,round(number/lut[ix]), pre[ix])
    }
    else if (rounding == T || is.numeric(digits)) {
        sistring <- paste(mysign,signif(number/lut[ix], digits), pre[ix],sep="")
    }
    else {
        sistring <- paste(mysign,number/lut[ix], pre[ix],sep="")
    } 
} else {
    sistring <- paste(mysign,as.character(number),sep="")
}
return(sistring)

}

于 2014-05-02T03:02:20.830 に答える