在previous question中,我询问基本R中是否存在方便的包装器以将数字格式化为百分比。
这引起了三个回应:
sprintf
,它可以高度灵活地格式化数字。在我看来,sprintf
函数对于R初学者来说只是有点过于模糊(除非它们来自C背景)。也许更好的解决方案是修改format
或prettyNum
以选择添加前缀和后缀,这样您就可以轻松创建百分比,货币,度数等。
问题:
您如何设计一个函数,类或一组函数来优雅地处理格式化数字,如百分比,货币,度数等?
答案 0 :(得分:10)
我可能会把事情变得非常简单。 format()
通常对大多数基本格式化需求很有用。我会用一个允许任意prefix
和suffix
字符串的简单包装来扩展它。这是一个简单的版本:
formatVal <- function(x, prefix = "", suffix = "", sep = "", collapse = NULL,
...) {
x <- format(x, ...)
x <- paste(prefix, x, suffix, sep = sep, collapse = collapse)
x
}
如果我真的这样做,我可能在collapse
的定义中没有formatVal()
参数,而是从...
处理它,但为了说明我保留了以上功能简单。
使用:
set.seed(1)
m <- runif(5)
一些简单的使用示例
> formatVal(m*100, suffix = "%")
[1] "26.55087%" "37.21239%" "57.28534%" "90.82078%" "20.16819%"
> formatVal(m*100, suffix = "%", digits = 2)
[1] "27%" "37%" "57%" "91%" "20%"
> formatVal(m*100, suffix = "%", digits = 2, nsmall = 2)
[1] "26.55%" "37.21%" "57.29%" "90.82%" "20.17%"
> formatVal(m, prefix = "£")
[1] "£0.2655087" "£0.3721239" "£0.5728534" "£0.9082078" "£0.2016819"
> formatVal(m, prefix = "£", digits = 1)
[1] "£0.3" "£0.4" "£0.6" "£0.9" "£0.2"
> formatVal(m, prefix = "£", digits = 1, nsmall = 2)
[1] "£0.27" "£0.37" "£0.57" "£0.91" "£0.20"
答案 1 :(得分:8)
print.formatted <- function(x)
{
print(paste(attr(x,"prefix"), sprintf(x*attr(x,"scaleFactor"),fmt=paste("%.",attr(x,"precision"),"f",sep="")), attr(x,"suffix"), sep=""))
}
as.percent <- function(x,precision=3)
{
class(x) <- c(class(x),"formatted")
attr(x,"scaleFactor")<-100
attr(x,"prefix")<-""
attr(x,"suffix")<-"%"
attr(x,"precision")<-precision
return(x)
}
as.currency <- function(x,prefix="£")
{
class(x) <- c(class(x),"formatted")
attr(x,"scaleFactor")<-1
attr(x,"prefix")<-prefix
attr(x,"suffix")<-""
attr(x,"precision")<-2
return(x)
}
as.percent(runif(3))
[1] "21.585%" "12.396%" "37.744%"
x <- as.currency(rnorm(3,500,100))
x
[1] "£381.93" "£339.49" "£521.74"
2*x
[1] "£763.86" "£678.98" "£1043.48"
答案 2 :(得分:4)
我认为这可以通过属性完成,例如:让v <- 3.4
。如果是英镑,我们可以使用类似的东西:
attributes(v)<-list(style = "descriptor", type = "currency", category = "pound")
如果是百分比:
attributes(v)<-list(style = "descriptor", type = "proportion", category = "percentage")
然后,需要一种特殊的打印方法。人们还可以结合翻译方法,例如从英镑兑换成美元(磅到美元),厘米到英寸等等。
descriptor
本质上是我对一种保留的标志的看法,用于指示给定数字的特殊处理。这可以稍后扩展到文本字符串,例如地址和名称。对于其他号码,例如电话号码,可能会对国家/地区代码,国家/地区区域/区域代码进行特殊分解,一直到分机。
对于数据类型,这样的包可能类似于ggplot
- 在类型中存储,转换和打印内容的特殊方法?
这样的系统可能会在乘以值时确保尺寸正确。这在许多应用程序中都具有实用性。
据我所知,R中单位的唯一广泛处理是字节(字节,KB,MB等)和时间(小时,秒等)。即便如此,处理虽然简单但并不明显 - 我仍然要告诉print
要使用的单位。例如,如果我想以KB为单位打印对象的大小,我不能简单地计算object.size(v)/1024
- 输出以一个字节的分数报告,而不是KB;我必须使用print(object.size(v), units = "K")
。
答案 3 :(得分:2)
ggplot2
有a bunch of functions用于格式化常见的特定情况。这些都是理想的,但对于两件事:它们不够通用,你不应该真正加载ggplot2
(包含所有它的依赖项)来获得这些函数。您可以尝试联系Hadley以更改签名以传递更多内容进行格式化,并将它们移至较低级别的包(plyr
或者自己的包ggtools
?)。