Làm thế nào để thêm số không hàng đầu?


351

Tôi có một bộ dữ liệu trông giống như thế này:

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

Tôi muốn thêm số 0 vào trước mỗi id động vật:

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

Và vì lợi ích, nếu tôi cần thêm hai hoặc ba số không trước id động vật thì sao?


6
Giả sử bạn muốn thêm n số không trước id động vật bạn chỉ cần làmdata$anim = paste(rep(0, n), data$anim, sep = "")
Ramnath

2
Khi bạn nói rằng bạn muốn "thêm số không", có lẽ bạn không muốn chuyển đổi các cột số nguyên của mình thành chuỗi / phân loại để thêm phần đệm vào bên trong dữ liệu, bạn muốn giữ số nguyên và chỉ in các số 0 đứng đầu khi kết xuất đầu ra .
smci

Câu trả lời:


553

Phiên bản ngắn: sử dụng formatChoặc sprintf.


Phiên bản dài hơn:

Có một số hàm có sẵn để định dạng số, bao gồm thêm các số 0 đứng đầu. Cái nào là tốt nhất phụ thuộc vào định dạng khác mà bạn muốn làm.

Ví dụ từ câu hỏi khá dễ vì tất cả các giá trị có cùng số chữ số để bắt đầu, vì vậy, hãy thử một ví dụ khó hơn về việc tạo ra các lũy thừa 10 chiều rộng 8.

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

paste(và đó là biến thể paste0) thường là các hàm thao tác chuỗi đầu tiên mà bạn gặp. Chúng không thực sự được thiết kế để thao túng các con số, nhưng chúng có thể được sử dụng cho điều đó. Trong trường hợp đơn giản, chúng ta luôn phải trả trước một số 0 duy nhất, paste0là giải pháp tốt nhất.

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

Đối với trường hợp có một số chữ số khác nhau trong các số, bạn phải tính toán thủ công có bao nhiêu số 0, điều này đủ khủng khiếp đến mức bạn chỉ nên làm điều đó vì tò mò bệnh hoạn.


str_padtừ stringrhoạt động tương tự như paste, làm cho rõ ràng hơn rằng bạn muốn đệm mọi thứ.

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

Một lần nữa, nó không thực sự được thiết kế để sử dụng với các con số, vì vậy trường hợp khó hơn đòi hỏi một chút suy nghĩ. Chúng ta chỉ nên nói "pad có số 0 đến chiều rộng 8", nhưng hãy nhìn vào đầu ra này:

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

Bạn cần đặt tùy chọn hình phạt khoa học để các số luôn được định dạng bằng cách sử dụng ký hiệu cố định (thay vì ký hiệu khoa học).

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

stri_padtrong stringicác công trình chính xác như str_padtừ stringr.


formatClà một giao diện đến chức năng C printf. Sử dụng nó đòi hỏi một số kiến ​​thức về arcana của chức năng cơ bản đó (xem liên kết). Trong trường hợp này, các điểm quan trọng là widthđối số, format"d""số nguyên" và là một "0" flagsố 0 chuẩn bị.

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"

Đây là giải pháp yêu thích của tôi, vì nó dễ dàng thay đổi độ rộng và chức năng đủ mạnh để thực hiện các thay đổi định dạng khác.


sprintflà một giao diện cho chức năng C cùng tên; thích formatCnhưng với một cú pháp khác nhau.

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

Ưu điểm chính sprintflà bạn có thể nhúng các số được định dạng bên trong các đoạn văn bản dài hơn.

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

Xem thêm câu trả lời của hàng hóa .


Để hoàn thiện, điều đáng nói là các hàm định dạng khác đôi khi hữu ích, nhưng không có phương pháp chuẩn bị số 0.

format, một hàm chung để định dạng bất kỳ loại đối tượng nào, với một phương thức cho các số. Nó hoạt động một chút như thế formatC, nhưng với một giao diện khác.

prettyNumlà một chức năng định dạng khác, chủ yếu để tạo nhãn đánh dấu trục thủ công. Nó hoạt động đặc biệt tốt cho phạm vi rộng của số.

Các scalesgói có một số chức năng như percent, date_formatdollarvới nhiều loại định dạng chuyên khoa.


3
cảm ơn rất nhiều vì sự giúp đỡ tuyệt vời Tôi đã sử dụng formatC để thêm các số 0 hàng đầu vào hoạt hình của mình và nó hoạt động tốt.
baz

2
formatC (số hoặc vectơ, width = 6, format = "d", flag = "0") hoạt động tốt (phiên bản R 3.0.2 (2013-09-25)). Cảm ơn.
Mohamad Fakih

1
sử dụng formatC () theo cách được mô tả ở trên không hiệu quả với tôi. Nó thêm không gian thay vì số không. Tôi đã làm gì sai sao? Tôi đang sử dụng phiên bản R 3.1.1.
user1816679

2
@ user1816679 Âm thanh như bạn quên flag = "0".
Bông Richie

1
Phần Chi tiết của ?sprintftrang trợ giúp mô tả điều này. "mn: Hai số cách nhau bởi một khoảng thời gian, biểu thị độ rộng trường (m) và độ chính xác (n)."
Richie Cotton

215

Đối với một giải pháp chung hoạt động bất kể có bao nhiêu chữ số data$anim, hãy sử dụng sprintfhàm. Nó hoạt động như thế này:

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

Trong trường hợp của bạn, bạn có thể muốn: data$anim <- sprintf("%06d", data$anim)


14
Lưu ý rằng sprintfchuyển đổi số thành chuỗi (ký tự).
aL3xa

Cảm ơn câu trả lời. Tôi muốn tạo một số gồm 13 chữ số thành 14 chữ số (thêm số 0 đứng đầu). Chức năng này dường như không hoạt động trong trường hợp này. Nó cho tôi một arror: Lỗi trong sprintf ("% 020d", 4000100000104): định dạng không hợp lệ '% 020d'; sử dụng định dạng% f,% e,% g hoặc% a cho các đối tượng số. Bất cứ đề nghị nào?
Rotail

Hãy thử: sprintf ("% 014.0f", 4000100000104)
Stewart Macdonald

sprintf không có sẵn cho R 3.4.1
Frank FYC

Vâng, đúng vậy. Nó không thay đổi kể từ phiên bản 1.5.0.
dash2

32

Mở rộng trên repsonse của @ hàng hóa:

Trong một số trường hợp, bạn có thể muốn đệm một chuỗi bằng số không (ví dụ: mã fips hoặc các yếu tố giống như số khác). Trong OSX / Linux:

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

Nhưng vì sprintf()gọi sprintf()lệnh C của HĐH , đã thảo luận ở đây , trong Windows 7, bạn nhận được một kết quả khác:

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

Vì vậy, trên các máy Windows, công việc xung quanh là:

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

1
Vì lý do nào, giải pháp này không còn hiệu quả với tôi trên Linux. @ kdauria str_padbây giờ là đi của tôi.
metasequoia

25

str_padtừ stringrgói là một thay thế.

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

4
Hãy rất cẩn thận str_padvì nó có thể dẫn đến kết quả bất ngờ. i.num = 600000; str_pad(i.num, width = 7, pad = "0") sẽ cung cấp cho bạn "006e + 05" chứ không phải "0600000"
Pankil Shah

2

Đây là một hàm R cơ sở tổng quát:

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)

Tôi thích sprintfnhưng nó đi kèm với hãy cẩn thận như:

tuy nhiên, việc triển khai thực tế sẽ tuân theo tiêu chuẩn C99 và các chi tiết tốt (đặc biệt là hành vi do lỗi người dùng) có thể phụ thuộc vào nền tảng


1

Đây là một cách khác để thêm dẫn đến 0 vào chuỗi như CUSIP đôi khi có thể trông giống như một số và nhiều ứng dụng như Excel sẽ bị hỏng và xóa số 0 hàng đầu hoặc chuyển chúng thành ký hiệu khoa học.

Khi tôi thử câu trả lời được cung cấp bởi @metasequoia, vectơ trả về có khoảng trắng ở đầu và không phải 0là s. Đây là cùng một vấn đề được đề cập bởi @ user1816679 - và xóa các trích dẫn xung quanh 0hoặc thay đổi từ %dthành %skhông tạo ra sự khác biệt. FYI, tôi đang sử dụng RStudio Server chạy trên Ubuntu Server. Giải pháp hai bước nhỏ này đã làm việc cho tôi:

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

sử dụng %>%chức năng ống từ magrittrgói, nó có thể trông như thế này:

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

Tôi muốn một giải pháp một chức năng, nhưng nó hoạt động.


0
data$anim <- sapply(0, paste0,data$anim)

Chỉ cần paste0(0, data$anim)làm việc tốt.
dash2

0

Đối với các trường hợp khác mà bạn muốn chuỗi số là nhất quán, tôi đã tạo một hàm.

Ai đó có thể thấy điều này hữu ích:

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)

Xin lỗi về định dạng.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.