Jak dodać początkowe zera?

Mam zestaw danych, który wygląda mniej więcej tak:

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

Chciałbym dodać zero przed każdym ID zwierzęcia:

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
A co, jeśli muszę dodać dwa lub trzy zera przed identyfikatorem zwierzęcia?
Author: Jaap, 2011-04-28

8 answers

Wersja skrócona: użyj formatC lub sprintf.


Dłuższa wersja:

Istnieje kilka funkcji do formatowania liczb, w tym dodawanie zer wiodących. Który z nich jest najlepszy zależy od tego, jakie inne formatowanie chcesz zrobić.

Przykład z pytania jest dość prosty, ponieważ wszystkie wartości mają tę samą liczbę cyfr, więc spróbujmy trudniejszego przykładu tworzenia potęg o szerokości 10 8 też.

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

paste (variant paste0) są często pierwszymi funkcjami manipulacji łańcuchami, z którymi się zetkniesz. Nie są one tak naprawdę przeznaczone do manipulowania liczbami, ale można je do tego wykorzystać. W prostym przypadku, w którym zawsze musimy poprzedzać pojedyncze zero, paste0 jest najlepszym rozwiązaniem.

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

W przypadku, gdy w liczbach jest zmienna liczba cyfr, musisz ręcznie obliczyć, ile zer ma być poprzedzonych, co jest na tyle straszne, że powinieneś to robić tylko z chorobliwej ciekawości.


str_pad from stringr działa podobnie do paste, dzięki czemu jest bardziej wyraźne, że chcesz podkładać rzeczy.

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

Ponownie, nie jest tak naprawdę zaprojektowany do użycia z liczbami, więc trudniejsza sprawa wymaga trochę zastanowienia. Nie jest to jednak żaden problem, ponieważ nie jest to możliwe.]}

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

Musisz ustawić karę naukową opcja tak, aby liczby były zawsze formatowane za pomocą notacji stałej (zamiast notacji naukowej).

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

stri_pad in stringi działa dokładnie tak jak str_pad z stringr.


formatC jest interfejsem do funkcji Cprintf. Korzystanie z niego wymaga pewnej wiedzy o arkanach tej podstawowej funkcji (patrz link). W tym przypadku istotnymi punktami jest argument width, format będący "d" dla "integer" oraz "0" flag do poprzedzania zer.

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"

Jest to moje ulubione rozwiązanie, ponieważ łatwo jest majstrować przy zmianie szerokości, a funkcja jest wystarczająco potężna, aby wprowadzić inne zmiany formatowania.


sprintf jest interfejsem do funkcji C O tej samej nazwie; podobnie jak formatC, ale z inną składnią.

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

Główną zaletą sprintf jest to, że można osadzać sformatowane liczby w dłuższych bitach tekst.

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

Zobacz także goodside ' s answer .


Dla kompletności warto wspomnieć o innych funkcjach formatowania, które są czasami przydatne, ale nie mają metody poprzedzania zer.

format, ogólna funkcja do formatowania dowolnego rodzaju obiektów, z metodą dla liczb. Działa trochę jak formatC, ale z jeszcze innym interfejsem.

prettyNum jest kolejnym formatowaniem funkcja, głównie do tworzenia ręcznych etykiet osi tick. Działa szczególnie dobrze dla szerokiego zakresu liczb.

The scales pakiet posiada kilka funkcji, takich jak percent, date_format oraz dollar dla formatów specjalistycznych.

 607
Author: Richie Cotton,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-25 15:06:08

Dla ogólnego rozwiązania, które działa niezależnie od liczby cyfr w data$anim, Użyj funkcji sprintf. Działa tak:

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

W Twoim przypadku prawdopodobnie chcesz: data$anim <- sprintf("%06d", data$anim)

 223
Author: goodside,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-24 02:38:24

Rozszerzenie na @goodside ' s repsonse:

W niektórych przypadkach możesz chcieć wstawić ciąg zer(np. kody fips lub inne czynniki numeryczne). W OSX / Linux:

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

Ale ponieważ sprintf() wywołuje polecenie C sprintf() OS, omówione tutaj , W Windows 7 otrzymujesz inny wynik:

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

Więc na maszynach z systemem Windows praca wokół jest:

> sprintf("%05d", as.numeric("104"))
[1] "00104"
 34
Author: metasequoia,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-21 14:41:18

str_pad z pakietu stringr jest alternatywą.

anim = 25499:25504
str_pad(anim, width=6, pad="0")
 28
Author: kdauria,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-27 06:56:47

Oto uogólnialna funkcja bazy R:

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)

Lubie sprintf ale ma takie zastrzeżenia jak:

Jednak rzeczywista implementacja będzie zgodna ze standardem C99 i drobne szczegóły (zwłaszcza zachowanie w przypadku błędu użytkownika) mogą zależeć od platformy

 2
Author: Tyler Rinker,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-27 02:15:50

Oto inna alternatywa dla dodawania prowadzących 0 do ciągów takich jak CUSIPs , które czasami mogą wyglądać jak liczba i które wiele aplikacji, takich jak Excel, uszkodzi i usunie wiodące 0 lub przekonwertuje je na notację naukową.

Kiedy próbowałem odpowiedzi podanej przez @ metasequoia, zwrócony wektor miał spacje wiodące, a nie 0 s. był to ten sam problem, o którym wspomniał @user1816679 -- i usunięcie cudzysłowów wokół 0 lub zmiana z %d na %s nie robi różnicy. Dla twojej wiadomości, używam serwera RStudio działającego na serwerze Ubuntu. To małe dwuetapowe rozwiązanie zadziałało dla mnie:

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

Używając funkcji %>% pipe z pakietu magrittr może to wyglądać tak:

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

Wolałbym rozwiązanie jednofunkcyjne, ale działa.
 1
Author: Ursus Frost,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-10 19:44:45
data$anim <- sapply(0, paste0,data$anim)
 0
Author: zhan2383,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-20 18:40:31

Dla innych okoliczności, w których chcesz, aby ciąg liczb był spójny, zrobiłem funkcję.

Ktoś może uznać to za przydatne:

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)

Przepraszam za formatowanie.

 0
Author: Phil,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-03 01:45:04