2017-10-10 7 views
0

Je cherchais un moyen de mettre en forme de grands nombres en R comme 2.3K ou 5.6M. J'ai trouvé this solution sur SO. Il s'avère que cela montre un comportement étrange pour certains vecteurs d'entrée.Comprendre la vectorisation

Voici ce que je suis en train de comprendre -

# 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) 

Nous pouvons voir que comprss(x) produit 0k comme le 5 ème élément qui est bizarre, mais comprss(x[5]) nous donne les résultats escomptés. L'élément 6 est encore plus étrange. Pour autant que je sache, toutes les fonctions utilisées dans le corps comprss sont vectorisées. Alors pourquoi ai-je encore besoin de sapply pour m'en sortir?

+1

Pitfalls de la programmation avec R! 'c (" "," K "," M ") [c (1,2,0,2)]' donne un vecteur de longueur 3, pas ce que vous voulez: '" "" K "" K "' . Cependant, 'c (" "," K "," M ") [0]' produit un vecteur de longueur 0: 'character (0)', qui fonctionne correctement à l'étape suivante, peut-être par accident. Le zéro arrive parce que '0.0' est en dehors des intervalles que vous avez fournis' findInterval() '. – bdemarest

+0

Veuillez également préciser si vous avez besoin de votre solution pour accepter des vecteurs de caractères ou des vecteurs numériques. Vos données d'exemple sont numériques, mais la fonction est écrite en supposant une saisie de caractères. – bdemarest

+0

Dans mon cas, l'entrée va toujours être numérique, je suis juste devenu paresseux et je n'ai pas modifié la fonction parce qu'elle fonctionnait très bien avec les vecteurs numériques. – Ameya

Répondre

1

est ici une version adaptée de vectorisée 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"