Wie füge ich führende Nullen hinzu?

351

Ich habe einen Datensatz, der ungefähr so ​​aussieht:

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

Ich möchte, dass vor jeder Tier-ID eine Null hinzugefügt wird:

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

Und was ist aus Interesse, wenn ich zwei oder drei Nullen vor den Tier-IDs hinzufügen muss?

baz
quelle
6
Angenommen, Sie möchten n Nullen vor Tier-IDs hinzufügen, die Sie nur tun müssendata$anim = paste(rep(0, n), data$anim, sep = "")
Ramnath
2
Wenn Sie sagen, dass Sie "Nullen hinzufügen" möchten, möchten Sie Ihre Ganzzahlspalten vermutlich nicht in Zeichenfolge / Kategorie konvertieren, um das Null-Auffüllen in den Daten selbst hinzuzufügen. Sie möchten sie ganzzahlig halten und nur führende Nullen drucken beim Rendern der Ausgabe .
smci

Antworten:

553

Die Kurzversion: benutze formatCoder sprintf.


Die längere Version:

Zum Formatieren von Zahlen stehen verschiedene Funktionen zur Verfügung, einschließlich des Hinzufügens führender Nullen. Welche am besten ist, hängt davon ab, welche andere Formatierung Sie vornehmen möchten.

Das Beispiel aus der Frage ist recht einfach, da alle Werte zunächst die gleiche Anzahl von Ziffern haben. Versuchen wir also ein härteres Beispiel für die Herstellung von Potenzen mit einer Breite von 10 und 8.

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

paste(und seine Variante paste0) sind oft die ersten Funktionen zur Manipulation von Zeichenfolgen, auf die Sie stoßen. Sie sind nicht wirklich für die Manipulation von Zahlen konzipiert, können aber dafür verwendet werden. In dem einfachen Fall, in dem wir immer eine einzelne Null voranstellen müssen, paste0ist dies die beste Lösung.

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

Für den Fall, dass die Zahlen eine variable Anzahl von Ziffern enthalten, müssen Sie manuell berechnen, wie viele Nullen vorangestellt werden müssen. Dies ist schrecklich genug, dass Sie dies nur aus krankhafter Neugier tun sollten.


str_padfrom stringrfunktioniert ähnlich wie pasteund macht es deutlicher, dass Sie Dinge auffüllen möchten.

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

Auch hier ist es nicht wirklich für die Verwendung mit Zahlen konzipiert, daher erfordert der schwierigere Fall ein wenig Nachdenken. Wir sollten nur "Pad mit Nullen bis Breite 8" sagen können, aber schauen Sie sich diese Ausgabe an:

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

Sie müssen die Option für wissenschaftliche Strafen so einstellen , dass Zahlen immer mit fester Notation (und nicht mit wissenschaftlicher Notation) formatiert werden.

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

stri_padin stringifunktioniert genau wie str_padab stringr.


formatCist eine Schnittstelle zur C-Funktion printf. Die Verwendung erfordert einige Kenntnisse des Arcana dieser zugrunde liegenden Funktion (siehe Link). In diesem Fall sind die wichtigen Punkte der widthArgumentation, formatwobei "d"für „integer“ und eine "0" flagfür das Voranstellen von Nullen.

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"

Dies ist meine Lieblingslösung, da es einfach ist, die Breite zu ändern, und die Funktion leistungsfähig genug ist, um andere Formatierungsänderungen vorzunehmen.


sprintfist eine Schnittstelle zur gleichnamigen C-Funktion; wie formatCaber mit einer anderen Syntax.

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

Der Hauptvorteil von sprintfist, dass Sie formatierte Zahlen in längere Textbits einbetten können.

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

Siehe auch die Antwort von goodside .


Der Vollständigkeit halber sind die anderen Formatierungsfunktionen zu erwähnen, die gelegentlich nützlich sind, aber keine Methode zum Voranstellen von Nullen haben.

format, eine generische Funktion zum Formatieren von Objekten aller Art mit einer Methode für Zahlen. Es funktioniert ein bisschen wie formatC, aber mit noch einer anderen Schnittstelle.

prettyNumist eine weitere Formatierungsfunktion, hauptsächlich zum Erstellen manueller Achsen-Tick-Beschriftungen. Es funktioniert besonders gut für große Zahlenbereiche.

Das scalesPaket hat mehrere Funktionen wie percent, date_formatund dollarfür die Fachformattypen.

Richie Cotton
quelle
3
Vielen Dank für die tolle Hilfe. Ich habe formatC verwendet, um meiner Animation führende Nullen hinzuzufügen, und es hat gut funktioniert.
baz
2
formatC (Zahl oder Vektor, Breite = 6, Format = "d", Flag = "0") hat gut funktioniert (R Version 3.0.2 (25.09.2013)). Vielen Dank.
Mohamad Fakih
1
Die Verwendung von formatC () auf die oben beschriebene Weise hat bei mir nicht funktioniert. Es wurden Leerzeichen anstelle von Nullen hinzugefügt. Habe ich etwas falsch gemacht? Ich verwende R Version 3.1.1.
user1816679
2
@ user1816679 Klingt so, als hättest du es vergessen flag = "0".
Richie Cotton
1
Der Abschnitt Details auf der ?sprintfHilfeseite beschreibt dies. "mn: Zwei durch einen Punkt getrennte Zahlen, die die Feldbreite (m) und die Genauigkeit (n) angeben."
Richie Cotton
215

data$animVerwenden Sie die sprintfFunktion für eine allgemeine Lösung, die unabhängig von der Anzahl der Ziffern funktioniert. Es funktioniert so:

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

In Ihrem Fall möchten Sie wahrscheinlich: data$anim <- sprintf("%06d", data$anim)

Gute Seite
quelle
14
Beachten Sie, dass sprintfnumerisch in Zeichenfolge (Zeichen) konvertiert wird.
aL3xa
Danke für die Antwort. Ich möchte eine 13-stellige Zahl auf 14-stellig setzen (addierende führende Null hinzufügen). Diese Funktion scheint in diesem Fall nicht zu funktionieren. Es gibt mir einen Arror: Fehler in sprintf ("% 020d", 4000100000104): ungültiges Format '% 020d'; Verwenden Sie für numerische Objekte das Format% f,% e,% g oder% a. Irgendein Vorschlag?
Rotail
Versuchen Sie: sprintf ("% 014.0f", 4000100000104)
Stewart Macdonald
Sprintf ist nicht verfügbar für R 3.4.1
Frank FYC
Ja, so ist es. Es ist seit Version 1.5.0 unverändert.
dash2
32

Erweiterung der Antwort von @ goodside:

In einigen Fällen möchten Sie möglicherweise eine Zeichenfolge mit Nullen auffüllen (z. B. Fips-Codes oder andere numerische Faktoren). In OSX / Linux:

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

Da sprintf()der hier beschriebenesprintf() Befehl C des Betriebssystems aufgerufen wird , erhalten Sie in Windows 7 ein anderes Ergebnis:

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

Auf Windows-Computern lautet die Problemumgehung also:

> sprintf("%05d", as.numeric("104"))
[1] "00104"
Metasequoia
quelle
1
Aus irgendeinem Grund funktioniert diese Lösung unter Linux nicht mehr für mich. @ kdauria str_padist jetzt mein go to.
Metasequoia
25

str_padaus dem stringrPaket ist eine Alternative.

anim = 25499:25504
str_pad(anim, width=6, pad="0")
kdauria
quelle
4
Seien Sie sehr vorsichtig, str_padda dies zu unerwarteten Ergebnissen führen kann. i.num = 600000;; str_pad(i.num, width = 7, pad = "0") gibt Ihnen "006e + 05" und nicht "0600000"
Pankil Shah
2

Hier ist eine verallgemeinerbare Basis-R-Funktion:

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)

Ich mag, sprintfaber es kommt mit Vorbehalten wie:

Die tatsächliche Implementierung folgt jedoch dem C99-Standard, und feine Details (insbesondere das Verhalten bei Benutzerfehlern) können von der Plattform abhängen

Tyler Rinker
quelle
1

Hier ist eine weitere Alternative zum Hinzufügen von führenden Nullen zu Zeichenfolgen wie CUSIPs, die manchmal wie eine Zahl aussehen können und bei denen viele Anwendungen wie Excel die führenden Nullen beschädigen und entfernen oder sie in wissenschaftliche Notation konvertieren.

Als ich die Antwort von @metasequoia versuchte, hatte der zurückgegebene Vektor führende Leerzeichen und nicht 0s. Dies war das gleiche Problem, das von @ user1816679 erwähnt wurde - und das Entfernen der Anführungszeichen um das 0oder das Ändern von %dzu %smachte auch keinen Unterschied. Zu Ihrer Information, ich verwende RStudio Server, der auf einem Ubuntu-Server ausgeführt wird. Diese kleine zweistufige Lösung hat bei mir funktioniert:

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

Mit der %>%Pipe-Funktion aus dem magrittrPaket könnte es so aussehen:

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

Ich würde eine Lösung mit einer Funktion bevorzugen, aber sie funktioniert.

Ursus Frost
quelle
0
data$anim <- sapply(0, paste0,data$anim)
zhan2383
quelle
paste0(0, data$anim)Würde einfach gut funktionieren.
dash2
0

Für andere Umstände, unter denen die Zahlenzeichenfolge konsistent sein soll, habe ich eine Funktion erstellt.

Jemand könnte dies nützlich finden:

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)

Entschuldigung für die Formatierung.

Phil
quelle