Bagaimana cara menambahkan angka nol di depan?

351

Saya memiliki satu set data yang terlihat seperti ini:

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

Saya ingin nol ditambahkan sebelum setiap id hewan:

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

Dan demi kepentingan, bagaimana jika saya perlu menambahkan dua atau tiga nol sebelum id hewan?

baz
sumber
6
Misalkan Anda ingin menambahkan nol sebelum id hewan yang perlu Anda lakukandata$anim = paste(rep(0, n), data$anim, sep = "")
Ramnath
2
Ketika Anda mengatakan Anda ingin "menambahkan nol", Anda mungkin tidak ingin mengubah kolom bilangan bulat Anda menjadi string / kategorikal untuk menambahkan nol-padding di dalam data itu sendiri, Anda ingin tetap bilangan bulat dan hanya mencetak nol di depan saat rendering output .
smci

Jawaban:

553

Versi singkat: gunakan formatCatau sprintf.


Versi yang lebih panjang:

Ada beberapa fungsi yang tersedia untuk memformat angka, termasuk menambahkan angka nol di depan. Yang mana yang terbaik tergantung pada format apa yang ingin Anda lakukan.

Contoh dari pertanyaan ini cukup mudah karena semua nilai memiliki jumlah digit yang sama untuk memulai, jadi mari kita coba contoh yang lebih sulit untuk membuat kekuatan 10 lebar 8 juga.

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

paste(dan variannya paste0) seringkali merupakan fungsi manipulasi string pertama yang Anda temui. Mereka tidak benar-benar dirancang untuk memanipulasi angka, tetapi mereka dapat digunakan untuk itu. Dalam kasus sederhana di mana kita selalu harus menambahkan satu nol, paste0adalah solusi terbaik.

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

Untuk kasus di mana ada jumlah variabel angka dalam angka, Anda harus menghitung secara manual berapa banyak nol untuk ditambahkan, yang cukup mengerikan sehingga Anda hanya harus melakukannya karena penasaran yang tidak wajar.


str_paddari stringrkarya yang mirip dengan paste, membuatnya lebih eksplisit bahwa Anda ingin memberi pad hal.

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

Sekali lagi, itu tidak benar-benar dirancang untuk digunakan dengan angka, sehingga kasus yang lebih sulit memerlukan sedikit pemikiran. Kita hanya bisa mengatakan "pad dengan nol ke lebar 8", tetapi lihat output ini:

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

Anda perlu mengatur opsi penalti ilmiah sehingga angka selalu diformat menggunakan notasi tetap (bukan notasi ilmiah).

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

stri_paddalam stringikarya persis seperti str_paddari stringr.


formatCadalah sebuah antarmuka untuk fungsi C printf. Menggunakannya membutuhkan beberapa pengetahuan tentang arcana dari fungsi yang mendasarinya (lihat tautan). Dalam hal ini, poin penting adalah widthargumen, formatyang "d"untuk "integer", dan "0" flaguntuk mengawali nol.

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"

Ini adalah solusi favorit saya, karena mudah untuk bermain-main dengan mengubah lebar, dan fungsinya cukup kuat untuk membuat perubahan format lainnya.


sprintfadalah antarmuka ke fungsi C dengan nama yang sama; suka formatCtetapi dengan sintaks yang berbeda.

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

Keuntungan utama sprintfadalah Anda dapat menyematkan angka yang diformat ke dalam bit teks yang lebih panjang.

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

Lihat juga jawaban goodside .


Untuk kelengkapannya, perlu disebutkan fungsi pemformatan lain yang kadang-kadang berguna, tetapi tidak memiliki metode untuk menambahkan nol.

format, fungsi generik untuk memformat objek apa pun, dengan metode untuk angka. Ini bekerja sedikit seperti formatC, tetapi dengan antarmuka yang lain.

prettyNumadalah fungsi pemformatan lain, sebagian besar untuk membuat label centang sumbu manual. Ini bekerja sangat baik untuk rentang angka yang luas.

The scalespaket memiliki beberapa fungsi seperti percent, date_formatdan dollaruntuk jenis format yang spesialis.

Richie Cotton
sumber
3
terima kasih banyak atas bantuannya. Saya menggunakan formatC untuk menambahkan nol terkemuka ke anim saya dan itu bekerja dengan baik.
baz
2
formatC (angka atau vektor, lebar = 6, format = "d", flag = "0") bekerja dengan baik (R versi 3.0.2 (2013-09-25)). Terima kasih.
Mohamad Fakih
1
menggunakan formatC () dengan cara yang dijelaskan di atas tidak bekerja untuk saya. Itu menambahkan spasi bukan nol. Apakah saya melakukan sesuatu yang salah? Saya menggunakan R versi 3.1.1.
user1816679
2
@ user1816679 Kedengarannya Anda lupa flag = "0".
Richie Cotton
1
Bagian Detail pada ?sprintfhalaman bantuan menjelaskan hal ini. "mn: Dua angka dipisahkan oleh tanda titik, menunjukkan lebar bidang (m) dan ketepatan (n)."
Richie Cotton
215

Untuk solusi umum yang berfungsi terlepas dari berapa banyak digit yang ada data$anim, gunakan sprintffungsi ini. Ini berfungsi seperti ini:

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

Dalam kasus Anda, Anda mungkin ingin: data$anim <- sprintf("%06d", data$anim)

sisi baik
sumber
14
Perhatikan bahwa sprintfmengubah angka menjadi string (karakter).
aL3xa
Terima kasih atas jawabannya. Saya ingin membuat angka 13-digit menjadi 14-digit (menambahkan nol di depan). Fungsi ini sepertinya tidak berfungsi untuk kasus ini. Ini memberi saya arror: Kesalahan dalam sprintf ("% 020d", 4000100000104): format tidak valid '% 020d'; gunakan format% f,% e,% g atau% a untuk objek numerik. Ada saran?
Rotail
Coba: sprintf ("% 014.0f", 4000100000104)
Stewart Macdonald
sprintf tidak tersedia untuk R 3.4.1
Frank FYC
Ya itu. Ini tidak berubah sejak versi 1.5.0.
dash2
33

Memperluas pada repsonse @ goodside:

Dalam beberapa kasus, Anda mungkin ingin menambahkan string dengan nol (misalnya kode fips atau faktor seperti numerik lainnya). Di OSX / Linux:

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

Tetapi karena sprintf()memanggil perintah OS C sprintf(), dibahas di sini , di Windows 7 Anda mendapatkan hasil yang berbeda:

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

Jadi pada mesin Windows yang bekerja di sekitar adalah:

> sprintf("%05d", as.numeric("104"))
[1] "00104"
metasequoia
sumber
1
Untuk alasan apa pun, solusi ini tidak lagi berfungsi untuk saya di Linux. @ kdauria str_padsekarang menjadi tujuan saya.
metasequoia
25

str_paddari stringrpaket adalah alternatif.

anim = 25499:25504
str_pad(anim, width=6, pad="0")
kdauria
sumber
4
Berhati-hatilah str_padkarena dapat menyebabkan hasil yang tidak terduga. i.num = 600000; str_pad(i.num, width = 7, pad = "0") akan memberi Anda "006e + 05" dan bukan "0600000"
Pankil Shah
2

Inilah fungsi dasar R yang dapat digeneralisasikan:

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)

Saya suka sprintftetapi disertai dengan peringatan seperti:

namun implementasi aktual akan mengikuti standar C99 dan detail halus (terutama perilaku di bawah kesalahan pengguna) mungkin tergantung pada platform

Tyler Rinker
sumber
1

Berikut ini adalah alternatif lain untuk menambahkan mengarah ke 0s ke string seperti CUSIPs yang kadang-kadang dapat terlihat seperti angka dan yang banyak aplikasi seperti Excel akan merusak dan menghapus 0s terkemuka atau mengubahnya menjadi notasi ilmiah.

Ketika saya mencoba jawaban yang diberikan oleh @metasequoia, vektor yang dikembalikan memiliki spasi terdepan dan bukan 0s. Ini adalah masalah yang sama yang disebutkan oleh @ user1816679 - dan menghapus tanda kutip di sekitar 0atau mengubah dari %dmenjadi %stidak membuat perbedaan juga. FYI, saya menggunakan RStudio Server yang berjalan di Server Ubuntu. Solusi dua langkah kecil ini bekerja untuk saya:

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

menggunakan %>%fungsi pipa dari magrittrpaket itu bisa terlihat seperti ini:

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

Saya lebih suka solusi satu-fungsi, tetapi berhasil.

Ursus Frost
sumber
0
data$anim <- sapply(0, paste0,data$anim)
zhan2383
sumber
Hanya paste0(0, data$anim)akan bekerja dengan baik.
dash2
0

Untuk keadaan lain di mana Anda ingin string angka konsisten, saya membuat suatu fungsi.

Seseorang mungkin menganggap ini berguna:

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)

Maaf tentang pemformatan.

Phil
sumber