您如何编写包装函数或类来将数字格式化为R中的百分比,货币等?

时间:2011-08-22 12:48:58

标签: r number-formatting

previous question中,我询问基本R中是否存在方便的包装器以将数字格式化为百分比。

这引起了三个回应:

  1. 可能不是。
  2. 这样的包装器太窄而无法使用。 useRs最好学习如何使用现有工具,例如sprintf,它可以高度灵活地格式化数字。
  3. 无论如何,这样的包装器是有问题的,因为你失去了对对象进行计算的能力。
  4. 在我看来,sprintf函数对于R初学者来说只是有点过于模糊(除非它们来自C背景)。也许更好的解决方案是修改formatprettyNum以选择添加前缀和后缀,这样您就可以轻松创建百分比,货币,度数等。


    问题:

    您如何设计一个函数,类或一组函数来优雅地处理格式化数字,如百分比,货币,度数等?

4 个答案:

答案 0 :(得分:10)

我可能会把事情变得非常简单。 format()通常对大多数基本格式化需求很有用。我会用一个允许任意prefixsuffix字符串的简单包装来扩展它。这是一个简单的版本:

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)

ggplot2a bunch of functions用于格式化常见的特定情况。这些都是理想的,但对于两件事:它们不够通用,你不应该真正加载ggplot2(包含所有它的依赖项)来获得这些函数。您可以尝试联系Hadley以更改签名以传递更多内容进行格式化,并将它们移至较低级别的包(plyr或者自己的包ggtools?)。