2017-10-10 56 views
0

我正在寻找一种方法来格式化R中的大数字2.3K5.6M。我在SO上找到了this解决方案。原来,它显示了一些输入向量的一些奇怪的行为。了解矢量化

这是我想了解 -

# Test vector with weird behaviour 
x <- c(302.456500093388, 32553.3619756151, 3323.71232001074, 12065.4076372462, 
    0, 6270.87962956305, 383.337515655172, 402.20778095643, 19466.0204345063, 
    1779.05474064539, 1467.09928489114, 3786.27112222457, 2080.08078309959, 
    51114.7097545816, 51188.7710104291, 59713.9414049798) 

# Formatting function for large numbers 
comprss <- function(tx) { 
    div <- findInterval(as.numeric(gsub("\\,", "", tx)), 
         c(1, 1e3, 1e6, 1e9, 1e12)) 
    paste(round(as.numeric(gsub("\\,","",tx))/10^(3*(div-1)), 1), 
     c('','K','M','B','T')[div], sep = '') 
} 

# Compare outputs for the following three commands 
x 
comprss(x) 
sapply(x, comprss) 

我们可以看到,comprss(x)产生0k为5 元件,其怪异,但comprss(x[5])给了我们预期的结果。元素更是更加奇特。

据我所知,comprss正文中使用的所有函数都是矢量化的。那么为什么我仍然需要sapply我的出路呢?

+1

有R编程的陷阱! 'c('“,”K“,”M“)[c(1,2,0,2)]产生一个长度为3的向量,不是你想要的:''”“K”“K” 。然而,'c(“”,“K”,“M”)[0]'会产生一个长度为0的向量:“字符(0)”,它可能在下一步中正常工作,可能是偶然的。由于'0.0'超出了为findInterval()提供的时间间隔,因此出现零。 – bdemarest

+0

另外,请说明您是否需要解决方案来接受字符向量或数字向量。您的示例数据是数字,但函数是在假定字符输入的情况下编写的。 – bdemarest

+0

在我的情况下,输入始终是数字,我只是变得懒惰,并没有修改函数,因为它在数字向量中工作得很好。 – Ameya

回答

1

这里是改编自pryr:::print.bytes向量化版本:

format_for_humans <- function(x, digits = 3){ 
    grouping <- pmax(floor(log(abs(x), 1000)), 0) 
    paste0(signif(x/(1000^grouping), digits = digits), 
      c('', 'K', 'M', 'B', 'T')[grouping + 1]) 
} 

format_for_humans(10^seq(0, 12, 2)) 
#> [1] "1" "100" "10K" "1M" "100M" "10B" "1T" 

x <- c(302.456500093388, 32553.3619756151, 3323.71232001074, 12065.4076372462, 
     0, 6270.87962956305, 383.337515655172, 402.20778095643, 19466.0204345063, 
     1779.05474064539, 1467.09928489114, 3786.27112222457, 2080.08078309959, 
     51114.7097545816, 51188.7710104291, 59713.9414049798) 

format_for_humans(x) 
#> [1] "302" "32.6K" "3.32K" "12.1K" "0"  "6.27K" "383" "402" 
#> [9] "19.5K" "1.78K" "1.47K" "3.79K" "2.08K" "51.1K" "51.2K" "59.7K" 

format_for_humans(x, digits = 1) 
#> [1] "300" "30K" "3K" "10K" "0" "6K" "400" "400" "20K" "2K" "1K" 
#> [12] "4K" "2K" "50K" "50K" "60K"