Rで数値をパーセンテージとしてフォーマットする方法は?


135

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がありますが、丸めの精度を制御できません。


5
sprintfメーリングリストのお気に入りの解決策のようです、そして私はこれ以上の解決策を見たことがありません。組み込み関数は、とにかく呼び出す方が簡単ではありませんよね?
michel-slm 2011

1
私の見解でsprintfは、たまたまプログラマーでもあるRコーダーのサブセットには完全に問題ありません。私はCOBOL(shedder)やfortran(私の年齢を示します)を含め、私の人生の多くの部分をコーディングしました。しかし、私はsprintfフォーマット規則を明白とは考えていません(翻訳:WTF?)。そしてもちろん、専用のラッパーは、例えば、sprintfのより呼び出すことが容易でなければならない:format_percent(x=0.12345, digits=2)
Andrie

@hircus私はそれがそれ自身の短いカレー機能に値するのに十分一般的だと思います。これは特にSweaveの問題で、\ Sexpr {sprintf(%1.2f %% "、myvar)}が\ Sexpr {pct(myvar)}よりもはるかに醜いか、またはより短い関数が何であれ
Ari B. Friedman

2
適切なツールの使用法を学習して、ユーザーが努力することを期待するべきではありませんか?sprintf()つまり、fooに含まれているパッケージを見つけるよりも、使い方の学習にほとんど時間がかかりませんformat_percent()。次に、ユーザーがパーセントとしてフォーマットしたくないが、他に似ているものがある場合はどうなりますか?彼らは別のラッパーを見つける必要があります。長期的には、基本ツールの学習は有益です。
Gavin Simpson

1
これには、%Rの「デフォルト」のレポート形式であるLaTeXのコメント文字というわずかな問題があります。そのため、グラフのラベル付けには役立ちますが、フォーマットされた数値をSwavedにする場合は注意が必要です。
James

回答:


118

さらに後で:

@DzimitryMによって指摘されたように、古い関数の同義語であるをpercent()支持して「廃止されました」。label_percent()percent_format()

label_percent() 関数を返すので、それを使用するには、追加の括弧のペアが必要です。

library(scales)
x <- c(-1, 0, 0.1, 0.555555, 1, 100)
label_percent()(x)
## [1] "-100%"   "0%"      "10%"     "56%"     "100%"    "10 000%"

括弧の最初のセット内に引数を追加して、これをカスタマイズします。

label_percent(big.mark = ",", suffix = " percent")(x)
## [1] "-100 percent"   "0 percent"      "10 percent"    
## [4] "56 percent"     "100 percent"    "10,000 percent"

数年後のアップデート:

最近では、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"。)


2
はい、これは機能し、質問で提供した回避策の少し一般的なバージョンです。しかし、私の本当の質問は、これがベースRに存在するかどうかです。
Andrie

で私の作品リストパーセントを、しかし、統計やグラフのコマンドで「パーセント(X)」の「X」を交換するとエラーメッセージが表示されます。
rolando2 14

@ rolando2私の回答とkrlmlrの回答はどちらも、数値ではなく文字ベクトルを出力として返します。軸ラベルなどをフォーマットするためのものです。おそらく100を掛けるだけですか?
リッチーコットン

2020年の時点でscales版 1.1.0マニュアルによると:percent()廃止されました。label_percent()代わりに使用してください。これは、数値のフォーマットには適していません。手巻きのソリューションが適切であるため
DzimitryM

74

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%"

2
負の数では機能しません。percent(-0.1)生産NaN%
akhmed

1
@akhmed:これはすでに報告されています。修正は利用可能ですが、レビュー待ちです:github.com/hadley/scales/issues/50。:それは、複数の負の数のための仕事に思われること注scales::percent(c(-0.1, -0.2))
krlmlr

リンクをありがとう!機能なのかバグなのかわかりません。複数の数値の場合、機能する場合と機能しない場合があります。セイは、scales::percent(c(-0.1,-0.1,-0.1))生成し"NaN%" "NaN%" "NaN%"たが、あなたの例では、作業を行います。他の人の参考のために、バグはの時点ではまだ修正されていませんscales_0.2.4。また、現在のところ、それを修正する対応するプルリクエストはまだメインブランチにマージされていません。
akhmed

34

パッケージpercentから関数をチェックしてくださいformattable

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

4
+1。これにより、含める桁数を指定できますscales::percentが、最初の2つの回答には含まれません。
Sam Firke 2016年

3
+1、独自の関数をロールするのは非常に簡単ですが、桁数を選択できることは非常に便利です。
Gang Su

10

私はこれらの回答の速度を評価するためにいくつかのベンチマークを実行し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()

8

この操作だけのために、scalesパッケージを使用できます(requireやライブラリを使用せずに)

scales::percent(m)

1
桁数の精度を上げる方法は?
Elmex80s

6

新しい関数を定義するための私の解決策は次のとおりです(ほとんどの場合、CurryとComposeで遊ぶことができます:-))。

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

3

scalable::percentすでに最も遅いことが示されていて、Liliana Pachecoが別のソリューションを提供しているのを見て、私は先に進み、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の例よりもはるかに悪い行きました。手がかりはありますか?


0
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

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

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)
}

基本的な算術はベクトル化されます---内部のforループは非効率的で不要です。と交換できますbase2[, j] = base[ , j] * 100 / suma.c。これは質問に対する正確な回答ではないことにも注意する必要があります...問題は0.5、計算を行うことではなく、「50.0%」のようなものをフォーマットすることについてです...
Gregor Thomas

0

tidyverseバージョンはこれです:

> library(tidyverse)

> set.seed(1)
> m <- runif(5)
> dt <- as.data.frame(m)

> dt %>% mutate(perc=scales::percent(m,accuracy=0.001))
          m    perc
1 0.2655087 26.551%
2 0.3721239 37.212%
3 0.5728534 57.285%
4 0.9082078 90.821%
5 0.2016819 20.168%

いつものようにきれいに見えます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.