web-dev-qa-db-ja.com

Rで数値をパーセントとしてフォーマットするにはどうすればよいですか?

Rの初心者として私を困惑させていたものの1つは、数値を印刷用のパーセンテージとしてフォーマットする方法でした。

たとえば、0.1234512.345%として表示します。これにはいくつかの回避策がありますが、これらのいずれも「初心者に優しい」とは思えません。例えば:

set.seed(1)
m <- runif(5)

paste(round(100*m, 2), "%", sep="")
[1] "26.55%" "37.21%" "57.29%" "90.82%" "20.17%"

sprintf("%1.2f%%", 100*m)
[1] "26.55%" "37.21%" "57.29%" "90.82%" "20.17%"

質問:これを行うベースR関数はありますか?あるいは、便利なラッパーを提供する広く使用されているパッケージはありますか?


?format?formatC、および?prettyNumでこのようなものを検索しましたが、ベースRで適切に便利なラッパーをまだ見つけていません。??"percent"は何も役に立ちませんでした。 library(sos); findFn("format percent")は1250ヒットを返します-そのため、再び役に立ちません。 ggplot2には関数percentがありますが、丸め精度を制御できません。

108
Andrie

数年後の更新:

最近では、krlmlrの回答に記載されているように、 percent パッケージに scales 関数があります。私の手巻きソリューションの代わりにそれを使用してください。


のようなものを試してください

percent <- function(x, digits = 2, format = "f", ...) {
  paste0(formatC(100 * x, format = format, digits = digits, ...), "%")
}

使用法、例えば、

x <- c(-1, 0, 0.1, 0.555555, 1, 100)
percent(x)

(必要に応じて、形式を"f"から"g"に変更します。)

105
Richie Cotton

scales パッケージを確認してください。以前はggplot2の一部だったと思います。

library('scales')
percent((1:10) / 100)
#  [1] "1%"  "2%"  "3%"  "4%"  "5%"  "6%"  "7%"  "8%"  "9%"  "10%"

精度を検出するための組み込みロジックは、ほとんどの場合に十分に機能するはずです。

percent((1:10) / 1000)
#  [1] "0.1%" "0.2%" "0.3%" "0.4%" "0.5%" "0.6%" "0.7%" "0.8%" "0.9%" "1.0%"
percent((1:10) / 100000)
#  [1] "0.001%" "0.002%" "0.003%" "0.004%" "0.005%" "0.006%" "0.007%" "0.008%"
#  [9] "0.009%" "0.010%"
percent(sqrt(seq(0, 1, by=0.1)))
#  [1] "0%"   "32%"  "45%"  "55%"  "63%"  "71%"  "77%"  "84%"  "89%"  "95%" 
# [11] "100%"
percent(seq(0, 0.1, by=0.01) ** 2)
#  [1] "0.00%" "0.01%" "0.04%" "0.09%" "0.16%" "0.25%" "0.36%" "0.49%" "0.64%"
# [10] "0.81%" "1.00%"
66
krlmlr

percentパッケージからformattable関数をチェックアウトします。

library(formattable)
x <- c(0.23, 0.95, 0.3)
percent(x)
[1] 23.00% 95.00% 30.00%
30
Liliana Pacheco

私はこれらの回答の速度についてベンチマークを行いましたが、percentパッケージのscalesがその緩慢さを理由に宣伝されていることに驚いていました。利点は、適切な書式設定のための自動検出器であると思いますが、データがどのように見えるかを知っていれば、避けるのは明らかです。

(0,1)の100,000パーセントのリストを2桁のパーセントにフォーマットしようとした結果は次のとおりです。

library(microbenchmark)
x = runif(1e5)
microbenchmark(times = 100L, andrie1(), andrie2(), richie(), krlmlr())
# Unit: milliseconds
#   expr       min        lq      mean    median        uq       max
# 1 andrie1()  91.08811  95.51952  99.54368  97.39548 102.75665 126.54918 #paste(round())
# 2 andrie2()  43.75678  45.56284  49.20919  47.42042  51.23483  69.10444 #sprintf()
# 3  richie()  79.35606  82.30379  87.29905  84.47743  90.38425 112.22889 #paste(formatC())
# 4  krlmlr() 243.19699 267.74435 304.16202 280.28878 311.41978 534.55904 #scales::percent()

したがって、sprintfは、パーセント記号を追加するときに明確な勝者として現れます。一方、数値を乗算して丸めるだけの場合(「%」を使用せずに割合から割合に変更する場合は、round()が最も高速です):

# Unit: milliseconds
#        expr      min        lq      mean    median        uq       max
# 1 andrie1()  4.43576  4.514349  4.583014  4.547911  4.640199  4.939159 # round()
# 2 andrie2() 42.26545 42.462963 43.229595 42.960719 43.642912 47.344517 # sprintf()
# 3  richie() 64.99420 65.872592 67.480730 66.731730 67.950658 96.722691 # formatC()
9
MichaelChirico

この操作のためだけにscalesパッケージを使用できます(requireまたはlibraryでロードせずに)

scales::percent(m)

新しい関数を定義するための私のソリューションは次のとおりです(ほとんどの場合、CurryとComposeをいじることができます:-)):

library(roxygen)
printpct <- Compose(function(x) x*100, Curry(sprintf,fmt="%1.2f%%"))
5
Ari B. Friedman

scalable::percentがすでに最も遅いことが示されており、リリアナ・パチェコが別のソリューションを提供しているのを見て、先に進み、Michaelセットの例に基づいて他のオプションのいくつかに対してベンチマークを試みました。

library(microbenchmark)
library(scales)
library(formattable)

x<-runif(1e5)

lilip <- function() formattable::percent(x,2)
krlmlr <- function() scales::percent(x)
andrie1 <- function() paste0(round(x,4) * 100, '%')

microbenchmark(times=100L,lilip(), krlmlr(), andrie1())

これらは私が得た結果です:

Unit: microseconds
      expr        min          lq        mean      median          uq        max neval
   lilip()    194.562    373.7335    772.5663    889.7045    950.4035   1611.537   100
  krlmlr() 226270.845 237985.6560 260194.9269 251581.0235 280704.2320 373022.180   100
 andrie1()  87916.021  90437.4820  92791.8923  92636.8420  94448.7040 102543.252   100

しかし、私のkrlmlr()andrie1()のパフォーマンスがMichaelChiricoの例よりもはるかに悪い理由はわかりません。手がかりはありますか?

3
matt_jay
try this~

data_format <- function(data,digit=2,type='%'){
if(type=='d') {
    type = 'f';
    digit = 0;
}
switch(type,
    '%' = {format <- paste("%.", digit, "f%", type, sep='');num <- 100},
    'f' = {format <- paste("%.", digit, type, sep='');num <- 1},
    cat(type, "is not a recognized type\n")
)
sprintf(format, num * data)
}
0
light-voice

この関数は、列ごとにデータをパーセンテージに変換できます

percent.colmns = function(base, columnas = 1:ncol(base), filas = 1:nrow(base)){
    base2 = base
    for(j in columnas){
        suma.c = sum(base[,j])
        for(i in filas){
            base2[i,j] = base[i,j]*100/suma.c
        }
    }
    return(base2)
}
0
Edwin Torres