Adicionando zeros à esquerda usando R

Eu tenho um dataset que se parece com algo assim:

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 

Eu gostaria que um zero fosse adicionado antes de cada id de 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 

E por interesse, e se eu precisar adicionar dois ou três zeros antes do id do animal?

A versão curta: use formatC ou sprintf .


A versão mais longa:

Existem várias funções disponíveis para a formatação de números, incluindo a adição de zeros à esquerda. Qual é o melhor depende de qual outra formatação você deseja fazer.

O exemplo da pergunta é bastante fácil, já que todos os valores têm o mesmo número de dígitos para começar, então vamos tentar um exemplo mais difícil de fazer potências de 10 de largura 8 também.

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

paste (e é variant paste0 ) são frequentemente as primeiras funções de manipulação de strings que você encontra. Eles não são realmente projetados para manipular números, mas podem ser usados ​​para isso. No caso simples em que sempre temos que preceder um único zero, o paste0 é a melhor solução.

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

Para o caso em que há um número variável de dígitos nos números, você precisa calcular manualmente quantos zeros preceder, o que é horrível o suficiente para que você o faça apenas por curiosidade mórbida.


str_pad de stringr funciona de forma semelhante a paste , tornando mais explícito que você deseja preencher as coisas.

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

Mais uma vez, não é realmente projetado para uso com números, então o caso mais difícil requer um pouco de reflection. Devemos apenas dizer "pad com zeros até a largura de 8", mas olhe para esta saída:

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

Você precisa definir a opção de penalidade científica para que os números sejam sempre formatados usando notação fixa (em vez de notação científica).

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

stri_pad in stringi funciona exatamente como str_pad de stringr .


formatC é uma interface para a function C printf . Usá-lo requer algum conhecimento dos arcana dessa function subjacente (ver link). Nesse caso, os pontos importantes são o argumento de width , o format sendo "d" para "inteiro" e um flag "0" para os zeros anteriores.

 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" 

Esta é a minha solução favorita, pois é fácil mexer na mudança de largura e a function é poderosa o suficiente para fazer outras alterações de formatação.


sprintf é uma interface para a function C com o mesmo nome; como formatC mas com uma syntax diferente.

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

A principal vantagem do sprintf é que você pode inserir números formatados em pedaços maiores de texto.

 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." 

Veja também a resposta da goodside .


Para completar, vale a pena mencionar as outras funções de formatação que são úteis ocasionalmente, mas não possuem nenhum método de zeros anteriores.

format , uma function genérica para formatar qualquer tipo de object, com um método para números. Funciona um pouco como formatC , mas com outra interface.

prettyNum é ainda outra function de formatação, principalmente para criar labels de marcação de eixo manuais. Ele funciona particularmente bem para grandes intervalos de números.

O pacote de scales tem várias funções, como percent , date_format e dollar para tipos de formato especializados.

Para uma solução geral que funciona independentemente de quantos dígitos estão em data$anim , use a function sprintf . Funciona assim:

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

No seu caso, você provavelmente data$anim < - sprintf("%06d", data$anim) querer: data$anim < - sprintf("%06d", data$anim)

Expandindo a repsonse da @ goodside:

Em alguns casos, você pode querer preencher uma string com zeros (por exemplo, códigos fips ou outros fatores de tipo numérico). No OSX / Linux:

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

Mas como o sprintf() chama o comando sprintf() do SO, discutido aqui , no Windows 7 você obtém um resultado diferente:

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

Então, nas máquinas Windows, o trabalho é:

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

str_pad do pacote stringr é uma alternativa.

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

Aqui está outra alternativa para adicionar leads a 0s a strings, como CUSIPs, que às vezes podem parecer um número e que muitos aplicativos, como o Excel, irão corromper e remover os 0s iniciais ou convertê-los em notação científica.

Quando tentei a resposta fornecida por @metasequoia, o vetor retornado tinha espaços iniciais e não 0 s. Este foi o mesmo problema mencionado por @ user1816679 – e remover as aspas em torno do 0 ou mudar de %d para %s também não fez diferença. FYI, estou usando o RStudio Server rodando em um servidor Ubuntu. Esta pequena solução de duas etapas funcionou para mim:

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

usando a function %>% pipe do pacote magrittr , pode ser assim:

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

Eu prefiro uma solução de function única, mas funciona.

Para outras circunstâncias em que você deseja que a cadeia numérica seja consistente, eu fiz uma function.

Alguém pode achar isso útil:

 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) 

Desculpe pela formatação.