小标题的数字打印格式

number printing format of tibbles

我正在尝试显示带有格式化数字的小标题,以便通过使用该数据类型的常用格式样式来简化 table 的阅读。

最理想的是,我在 ggplot2 的 scales 包行中搜索一些东西,这样可能会出现以下情况:

t <- tibble(
    surface = c(98000, 178000000000, 254000000), 
    price = c(517244, 939484, 1340612), 
    rate = c(0.12, 0.07, 0.045)
)
print(t,
    label = c(
        surface = label_number_si(),
        price = label_dollar(),
        rate = label_percent()
    )
)
# A tibble: 3 x 3
    surface   price    rate
     <dbl>    <dbl>    <dbl>
1      98k $  517 244  12.0% 
2     178B $  939 484   7.0% 
3     254M  340 612   4.5%

目前在打印 tibble 时,我收到以下输出,很难阅读,尤其是价格栏:

print(t)
# A tibble: 3 x 3
       surface   price  rate
         <dbl>   <dbl> <dbl>
1        98000  517244 0.12 
2 178000000000  939484 0.07 
3    254000000 1340612 0.045

发现的所有类似问题,例如 or 似乎都围绕使用 options(scipen = xxx) 的科学记数法展开,这实际上不允许根据需要定义输出。

我也尝试寻找其他包,例如 units,但这些包也不提供特定的数字格式,仅提供单位到列类型的附件。

您可以使用 scales::dollar() 来格式化价格,sprintf() 来格式化汇率,还有一个辅助函数来格式化 surface(我从 here 那里借来的) .

library(dplyr)

t <- tibble(
  surface = c(98000, 178000000000, 254000000), 
  price = c(517244, 939484, 1340612), 
  rate = c(0.12, 0.07, 0.045)
)

si_number = function(x, digits) {

  compress = function(x, n) {
    signif(x * 10^(-n), digits)
  }

  case_when(
    x >= 1e9   ~ paste0(compress(x, 9), "B"),
    x >= 1e6   ~ paste0(compress(x, 6), "M"),
    x >= 1000  ~ paste0(compress(x, 3), "k"),
    x >= 1     ~ as.character(compress(x, 0))
  )
}

t2 <- t %>%
  mutate(
    surface = si_number(surface, 3),
    price   = scales::dollar(price),
    rate    = sprintf("%.1f%%", rate * 100)
  )

t2
#> # A tibble: 3 x 3
#>   surface price      rate 
#>   <chr>   <chr>      <chr>
#> 1 98k     7,244   12.0%
#> 2 178B    9,484   7.0% 
#> 3 254M    ,340,612 4.5%

reprex package (v0.3.0)

于 2020 年 2 月 24 日创建

更改打印的 tibble 格式的最简单方法是创建一个函数来打印 tibble 的变异版本。

您可以使用一些非标准的评估来传递您喜欢的任何函数以应用于每一列。这非常接近你想要的我认为:

library(tidyverse)
library(scales)

format_tibble <- function(tbl, ...)
{
  functions <- rlang::dots_list(...)
  if(length(functions) > 0)
  {
    if(length(tbl) < length(functions)) functions <- functions[seq_along(tbl)]
    columns <- names(functions)
    for(i in seq_along(columns))
    {
      fun <- functions[[i]]
      col <- as.name(columns[i])
      tbl <- mutate(tbl, !!quo_name(col) := fun(!!enquo(col)))
    }
  }
  print(tbl)
}

所以现在,开始你的小玩意:

t <- tibble( surface = c(98000, 178000000000, 254000000), 
             price   = c(517244, 939484, 1340612), 
             rate    = c(0.12, 0.07, 0.045))

我们只需要这样做:

t %>%
format_tibble(surface = label_number_si(),
              price   = label_dollar(),
              rate    = label_percent())
#> # A tibble: 3 x 3
#>   surface price      rate 
#>   <chr>   <chr>      <chr>
#> 1 98K     7,244   12.0%
#> 2 178B    9,484   7.0% 
#> 3 254M    ,340,612 4.5%

reprex package (v0.3.0)

于 2020 年 2 月 25 日创建

解决方法是将数据作为字符向量处理:

library(tibble)

options(scipen = 12)

t <- tibble(
  surface = c(98000, 178000000000, 254000000), 
  price = c(517244, 939484, 1340612), 
  rate = c(0.12, 0.07, 0.045)
)
# temp vars
t$KMB <- ifelse(t$surface >= 10^3 & t$surface < 10^6, "K",
  ifelse(t$surface >= 10^6 & t$surface < 10^9, "M", "B"))
t$surface_char <- gsub("0", "", as.character(t$surface))

# paste elements together
t$surface <- paste0(t$surface_char, t$KMB)        
t$price <- paste0("$ ", t$price)
t$rate <- paste0(as.character(format(t$rate *100, nsmall = 1)), "%")

# remove temp vars
t$KMB <- NULL
t$surface_char <- NULL

print(t)