web-dev-qa-db-fra.com

Comment ajouter des zéros au début?

J'ai un ensemble de données qui ressemble à ceci:

anim <- c(25499,25500,25501,25502,25503,25504)
sex  <- c(1,2,2,1,2,1)
wt   <- c(0.8,1.2,1.0,2.0,1.8,1.4)
data <- data.frame(anim,sex,wt)

data
   anim sex  wt anim2
1 25499   1 0.8     2
2 25500   2 1.2     2
3 25501   2 1.0     2
4 25502   1 2.0     2
5 25503   2 1.8     2
6 25504   1 1.4     2

Je voudrais qu'un zéro soit ajouté avant chaque identifiant d'animal:

data
   anim sex  wt anim2
1 025499   1 0.8     2
2 025500   2 1.2     2
3 025501   2 1.0     2
4 025502   1 2.0     2
5 025503   2 1.8     2
6 025504   1 1.4     2

Et par souci d’intérêt, si j’ai besoin d’ajouter deux ou trois zéros avant l’identifiant de l’animal?

309
baz

La version courte: use formatC ou sprintf .


La version la plus longue:

Plusieurs fonctions sont disponibles pour formater les nombres, notamment l’ajout de zéros non significatifs. Le meilleur choix dépend du formatage que vous souhaitez utiliser.

L'exemple de la question est assez simple, car toutes les valeurs ont le même nombre de chiffres pour commencer. Essayons donc de donner un exemple plus précis de la création de puissances de 10 largeur 8 également.

_anim <- 25499:25504
x <- 10 ^ (0:5)
_

paste (et sa variante _paste0_) sont souvent les premières fonctions de manipulation de chaînes que vous rencontrez. Ils ne sont pas vraiment conçus pour manipuler des nombres, mais ils peuvent être utilisés pour cela. Dans le cas simple où nous devons toujours ajouter un zéro, _paste0_ est la meilleure solution.

_paste0("0", anim)
## [1] "025499" "025500" "025501" "025502" "025503" "025504"
_

Dans le cas où le nombre de chiffres est variable, vous devez calculer manuellement le nombre de zéros à ajouter, ce qui est assez horrible pour que vous ne puissiez le faire que par curiosité morbide.


str_pad de stringr fonctionne de la même manière que paste, ce qui rend plus explicite le fait que vous souhaitez enregistrer des éléments.

_library(stringr)
str_pad(anim, 6, pad = "0")
## [1] "025499" "025500" "025501" "025502" "025503" "025504"
_

Encore une fois, ce n'est pas vraiment conçu pour être utilisé avec des chiffres, donc le cas le plus difficile nécessite un peu de réflexion. Nous devrions juste être capable de dire "pad avec des zéros à la largeur 8", mais regardez cette sortie:

_str_pad(x, 8, pad = "0")
## [1] "00000001" "00000010" "00000100" "00001000" "00010000" "0001e+05"
_

Vous devez définir la pénalité scientifique option pour que les nombres soient toujours mis en forme en utilisant une notation fixe (plutôt qu'une notation scientifique).

_library(withr)
with_options(
  c(scipen = 999), 
  str_pad(x, 8, pad = "0")
)
## [1] "00000001" "00000010" "00000100" "00001000" "00010000" "00100000"
_

stri_pad dans stringi fonctionne exactement comme _str_pad_ de stringr.


formatC est une interface avec la fonction C printf . Son utilisation nécessite une connaissance des arcanes de cette fonction sous-jacente (voir lien). Dans ce cas, les points importants sont l'argument width, format étant _"d"_ pour "entier" et un _"0"_ flag pour les zéros ajoutés.

_formatC(anim, width = 6, format = "d", flag = "0")
## [1] "025499" "025500" "025501" "025502" "025503" "025504"
formatC(x, width = 8, format = "d", flag = "0")
## [1] "00000001" "00000010" "00000100" "00001000" "00010000" "00100000"
_

C'est ma solution préférée, car il est facile de modifier la largeur et la fonction est suffisamment puissante pour apporter d'autres modifications de formatage.


sprintf est une interface avec la fonction C du même nom; comme formatC mais avec une syntaxe différente.

_sprintf("%06d", anim)
## [1] "025499" "025500" "025501" "025502" "025503" "025504"
sprintf("%08d", x)
## [1] "00000001" "00000010" "00000100" "00001000" "00010000" "00100000"
_

Le principal avantage de sprintf est que vous pouvez incorporer des nombres mis en forme dans des bits de texte plus longs.

_sprintf(
  "Animal ID %06d was a %s.", 
  anim, 
  sample(c("lion", "tiger"), length(anim), replace = TRUE)
)
## [1] "Animal ID 025499 was a tiger." "Animal ID 025500 was a tiger."
## [3] "Animal ID 025501 was a lion."  "Animal ID 025502 was a tiger."
## [5] "Animal ID 025503 was a tiger." "Animal ID 025504 was a lion." 
_

Voir aussi réponse de goodside .


Pour être complet, il convient de mentionner les autres fonctions de formatage qui sont parfois utiles, mais ne disposent pas de méthode de préfixe des zéros.

format, une fonction générique permettant de formater tout type d'objet, avec une méthode pour les nombres. Cela fonctionne un peu comme formatC, mais avec encore une autre interface.

prettyNum est une autre fonction de formatage, principalement destinée à la création d'étiquettes de ticks d'axes manuelles. Cela fonctionne particulièrement bien pour une large gamme de nombres.

Le package scales possède plusieurs fonctions telles que percent , date_format et dollar pour les types de formats spécialisés.

488
Richie Cotton

Pour une solution générale fonctionnant quel que soit le nombre de chiffres de data$anim, utilisez la fonction sprintf. Cela fonctionne comme ceci:

sprintf("%04d", 1)
# [1] "0001"
sprintf("%04d", 104)
# [1] "0104"
sprintf("%010d", 104)
# [1] "0000000104"

Dans votre cas, vous voulez probablement: data$anim <- sprintf("%06d", data$anim)

200
goodside

Développer la réponse de @ goodside:

Dans certains cas, il peut être utile de remplir une chaîne de caractères avec des zéros (par exemple, des codes fips ou d'autres facteurs de type numérique). Sous OSX/Linux:

> sprintf("%05s", "104")
[1] "00104"

Mais parce que sprintf() appelle la commande C sprintf() du système d'exploitation, discutée ici , sous Windows 7, vous obtenez un résultat différent:

> sprintf("%05s", "104")
[1] "  104"

Donc, sur les machines Windows, le travail consiste à:

> sprintf("%05d", as.numeric("104"))
[1] "00104"
29
metasequoia

str_pad du package stringr est une alternative.

anim = 25499:25504
str_pad(anim, width=6, pad="0")
21
kdauria
data$anim <- sapply(0, paste0,data$anim)
2
zhan2383

Voici une fonction de base R généralisable:

pad_left <- function(x, len = 1 + max(nchar(x)), char = '0'){

    unlist(lapply(x, function(x) {
        paste0(
            paste(rep(char, len - nchar(x)), collapse = ''),
            x
        )
    }))
}

pad_left(1:100)

J'aime sprintf mais il comporte des avertissements tels que:

toutefois, l'implémentation réelle suivra la norme C99 et des détails précis (en particulier le comportement en cas d'erreur utilisateur) peuvent dépendre de la plate-forme.

2
Tyler Rinker

Voici une autre alternative pour ajouter des caractères 0 à des chaînes telles que CUSIPs qui peut parfois ressembler à un nombre et que de nombreuses applications telles que Excel corrompent et suppriment les 0 ou les convertissent en notation scientifique.

Lorsque j'ai essayé la réponse fournie par @metasequoia, le vecteur renvoyé avait des espaces et non des 0s. C'était le même problème mentionné par @ user1816679 - et supprimer les guillemets autour du 0 ou passer de %d à %s ne faisait pas de différence non plus. Pour votre information, j'utilise RStudio Server sur un serveur Ubuntu. Cette petite solution en deux étapes a fonctionné pour moi:

gsub(pattern = " ", replacement = "0", x = sprintf(fmt = "%09s", ids[,CUSIP]))

en utilisant la fonction de pipe %>% du paquetage magrittr, cela pourrait ressembler à ceci:

sprintf(fmt = "%09s", ids[,CUSIP]) %>% gsub(pattern = " ", replacement = "0", x = .)

Je préférerais une solution à fonction unique, mais cela fonctionne.

1
Ursus Frost

Pour d'autres circonstances dans lesquelles vous voulez que la chaîne numérique soit cohérente, j'ai créé une fonction.

Quelqu'un peut trouver cela utile:

idnamer<-function(x,y){#Alphabetical designation and number of integers required
    id<-c(1:y)
    for (i in 1:length(id)){
         if(nchar(id[i])<2){
            id[i]<-paste("0",id[i],sep="")
         }
    }
    id<-paste(x,id,sep="")
    return(id)
}
idnamer("EF",28)

Désolé pour le formatage.

1
Phil