Rの初心者として私を困惑させていたものの1つは、数値を印刷用のパーセンテージとしてフォーマットする方法でした。
たとえば、0.12345
を12.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
がありますが、丸め精度を制御できません。
数年後の更新:
最近では、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"
に変更します。)
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%"
percent
パッケージからformattable
関数をチェックアウトします。
library(formattable)
x <- c(0.23, 0.95, 0.3)
percent(x)
[1] 23.00% 95.00% 30.00%
私はこれらの回答の速度についてベンチマークを行いましたが、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()
この操作のためだけにscalesパッケージを使用できます(requireまたはlibraryでロードせずに)
scales::percent(m)
新しい関数を定義するための私のソリューションは次のとおりです(ほとんどの場合、CurryとComposeをいじることができます:-)):
library(roxygen)
printpct <- Compose(function(x) x*100, Curry(sprintf,fmt="%1.2f%%"))
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の例よりもはるかに悪い理由はわかりません。手がかりはありますか?
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)
}
この関数は、列ごとにデータをパーセンテージに変換できます
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)
}