Как отформатировать число в процентах в R?
одна из вещей, которые раньше озадачивали меня как новичка в R, заключалась в том, как форматировать число в процентах для печати.
например, display 0.12345 как 12.345%. У меня есть несколько обходных путей для этого, но ни один из них не кажется "Newby friendly". Например:
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 но это не дает никакого контроля над точностью округления.
9 ответов:
обновление, несколько лет спустя:
в эти дни есть
percent
Проверьте
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наscalesпакет так рекламируется, учитывая его вялость. Я предполагаю, что преимуществом является его автоматический детектор для правильного форматирования, но если вы знаете, как выглядят ваши данные, кажется, что этого следует избегать.вот результаты от попытки форматировать список из 100 000 процентов в (0,1) до процента в 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()
вот мое решение для определения новой функции (в основном, чтобы я мог играть с Карри и сочинять: -)):
library(roxygen) printpct <- Compose(function(x) x*100, Curry(sprintf,fmt="%1.2f%%"))
видя, как
scalable::percentуже было показано, что он самый медленный, и Лилиана Пачеко предложила другое решение, я пошел вперед и попытался сравнить его с некоторыми другими вариантами, основанными на примере Майкла: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()выступал намного хуже, чем в Примере Михаэльчирико. Какие-нибудь улики?
вы можете использовать пакет scales только для этой операции (без загрузки его с require или библиотекой)
scales::percent(m)
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) }
Comments