Jak dodać zera wiodące?


351

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 identyfikatorem 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 na wszelki wypadek, co jeśli muszę dodać dwa lub trzy zera przed identyfikatorem zwierzęcia?


6
Załóżmy, że chcesz dodać n zer przed identyfikatorami zwierząt, po prostu musisz to zrobićdata$anim = paste(rep(0, n), data$anim, sep = "")
Ramnath

2
Kiedy mówisz, że chcesz „dodać zera”, prawdopodobnie nie chcesz konwertować kolumn liczb całkowitych na ciąg / kategorialne, aby dodać dopełnianie zera w samych danych, chcesz zachować ich liczby całkowite i drukować tylko zera wiodące podczas renderowania danych wyjściowych .
smci

Odpowiedzi:


552

Wersja skrócona: użyj formatClub sprintf.


Dłuższa wersja:

Dostępnych jest kilka funkcji formatowania liczb, w tym dodawanie zer wiodących. Wybór najlepszego zależy od tego, jakie inne formatowanie chcesz wykonać.

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

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

paste(i jest to wariant paste0) są często pierwszymi napotkanymi funkcjami manipulacji ciągami. Nie są tak naprawdę zaprojektowane do manipulowania liczbami, ale można do tego użyć. W prostym przypadku, w którym zawsze musimy wstawić jedno zero, paste0jest 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ć liczbę zer do uzupełnienia, co jest na tyle okropne, że powinieneś to zrobić tylko z chorobliwej ciekawości.


str_padod stringrdziała podobnie do paste, czyniąc bardziej wyraźnym, że chcesz uzupełniać.

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

Ponownie, nie jest tak naprawdę przeznaczony do używania z liczbami, więc trudniejszy przypadek wymaga trochę myślenia. Powinniśmy być w stanie powiedzieć „pad z zerami do szerokości 8”, ale spójrzmy na ten wynik:

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

Musisz ustawić opcję kary naukowej , aby liczby były zawsze formatowane przy użyciu stałej notacji (a nie notacji naukowej).

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

stri_padw stringidziełach dokładnie takich jak str_padz stringr.


formatCjest interfejsem funkcji C printf. Korzystanie z niej wymaga pewnej wiedzy na temat arkanów tej podstawowej funkcji (patrz link). W tym przypadku ważne punkty są widthargumentem, formatbędąc "d"na „całkowitą”, a "0" flagna poprzedzenie zerami.

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"

To moje ulubione rozwiązanie, ponieważ łatwo jest majstrować przy zmianie szerokości, a funkcja jest wystarczająco potężna, aby dokonywać innych zmian formatowania.


sprintfjest interfejsem do funkcji C o tej samej nazwie; jak, formatCale 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ą sprintfjest to, że można osadzić sformatowane liczby w dłuższych fragmentach tekstu.

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 odpowiedź goodside .


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

format, ogólna funkcja do formatowania dowolnego rodzaju obiektu, z metodą liczbową. Działa trochę podobnie formatC, ale z jeszcze innym interfejsem.

prettyNumto kolejna funkcja formatowania, głównie do tworzenia ręcznych etykiet zaznaczenia osi. Działa szczególnie dobrze w szerokim zakresie liczb.

scalesPakiet ma kilka funkcji, takich jak percent, date_formati dollardla typów formatów specjalistycznych.


3
wielkie dzięki za wspaniałą pomoc. Użyłem formatu C, aby dodać zera wiodące do mojego animu i działało to dobrze.
baz

2
Format C (liczba lub wektor, szerokość = 6, format = „d”, flaga = „0”) działał dobrze (wersja R 3.0.2 (2013-09-25)). Dzięki.
Mohamad Fakih

1
użycie formatu C () w sposób opisany powyżej nie działało dla mnie. Dodał spacje zamiast zer. Czy zrobiłem coś złego? Używam wersji R 3.1.1.
user1816679,

2
@ user1816679 Brzmi jak zapomniałeś flag = "0".
Richie Cotton,

1
?sprintfOpisuje to sekcja Szczegóły na stronie pomocy. „mn: Dwie liczby oddzielone kropką, oznaczające szerokość pola (m) i dokładność (n).”
Richie Cotton,

215

Aby uzyskać ogólne rozwiązanie, które działa niezależnie od liczby cyfr data$anim, użyj sprintffunkcji. Działa to 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)


14
Zauważ, że sprintfkonwertuje liczbę na ciąg (znak).
aL3xa

Dziękuję za odpowiedź. Chcę zrobić 13-cyfrową liczbę do 14 cyfr (dodając początkowe zero). Ta funkcja nie działa w tym przypadku. Daje mi błąd: błąd w sprintf („% 020d”, 4000100000104): nieprawidłowy format „% 020d”; użyj formatu% f,% e,% g lub% a dla obiektów numerycznych. Jakieś sugestie?
Rotail

Wypróbuj: sprintf ("% 014.0f", 4000100000104)
Stewart Macdonald

sprintf nie jest dostępny dla R 3.4.1
Frank FYC

Tak to jest. Nie zmienia się od wersji 1.5.0.
dash2

32

Rozwijanie odpowiedzi @ goodside's:

W niektórych przypadkach możesz chcieć uzupełnić ciąg zerami (np. Kody fips lub inne czynniki numeryczne). W OSX / Linux:

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

Ale ponieważ sprintf()wywołuje sprintf()komendę C systemu operacyjnego , omówioną tutaj , w Windows 7 otrzymujesz inny wynik:

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

Na komputerach z systemem Windows obejście:

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

1
Z jakiegokolwiek powodu to rozwiązanie nie działa już dla mnie w systemie Linux. @ kdauria's str_padjest teraz moją drogą do.
metasequoia

25

str_padz stringrpaczki jest alternatywą.

anim = 25499:25504
str_pad(anim, width=6, pad="0")

4
Bądź bardzo ostrożny, str_padponieważ może to prowadzić do nieoczekiwanych rezultatów. i.num = 600000; str_pad(i.num, width = 7, pad = "0") da ci „006e + 05”, a nie „0600000”
Pankil Shah

2

Oto uogólniająca podstawowa funkcja 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)

Podoba mi się, sprintfale zawiera pewne zastrzeżenia:

jednak rzeczywista implementacja będzie zgodna ze standardem C99, a dokładne szczegóły (szczególnie zachowanie pod błędem użytkownika) mogą zależeć od platformy


1

Oto kolejna alternatywa dla dodawania wiodących zer do ciągów takich jak CUSIP, które czasami mogą wyglądać jak liczby i które wiele aplikacji, takich jak Excel, uszkodzi i usunie wiodące zera lub przekształci je w notację naukową.

Kiedy próbowałem odpowiedzi dostarczonej przez @metasequoia, zwrócony wektor miał wiodące spacje, a nie 0s. Był to ten sam problem, o którym wspominał @ user1816679 - i usunięcie cudzysłowów wokół 0lub zmiana z %dna %srównież nie miało znaczenia. Do Twojej wiadomości używam RStudio Server działającego na serwerze Ubuntu. To małe dwustopniowe rozwiązanie działało dla mnie:

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

przy użyciu %>%funkcji potoku z magrittrpakietu może wyglądać następująco:

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

Wolałbym rozwiązanie jednofunkcyjne, ale działa.



0

Dla innych okoliczności, w których chcesz, aby ciąg liczb był spójny, utworzył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)

Przepraszamy za formatowanie.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.