Як додати провідні нулі?


352

У мене є набір даних, який виглядає приблизно так:

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

Я хотів би додати нуль перед кожним ідентифікатором тварини:

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

І заради інтересу, що, якщо мені потрібно додати дві-три нулі перед ідентифікатором тварини?


6
Припустимо, ви хочете додати нулі перед ідентифікаційними тваринамиdata$anim = paste(rep(0, n), data$anim, sep = "")
Ramnath,

2
Коли ви говорите, що хочете "додати нулі", ви, мабуть, не хочете перетворювати цілі цілі стовпці в рядкові / категоричні, щоб додати нульові прокладки всередині самих даних, ви хочете зберегти їх цілими і друкувати лише провідні нулі при виведенні виводу .
smci

Відповіді:


555

Коротка версія: використовувати formatCабо sprintf.


Більш довга версія:

Існує кілька функцій для форматування чисел, включаючи додавання провідних нулів. Який із них найкращий, залежить від того, яке ще форматування ви хочете зробити.

Приклад із запитання досить простий, оскільки всі значення мають однакову кількість цифр для початку, тому давайте спробуємо більш складний приклад створення потужностей 10 шириною 8.

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

paste(і це варіант paste0) часто є першими функціями маніпулювання струнами, які ви стикаєтеся. Вони насправді не призначені для маніпулювання цифрами, але їх можна використовувати для цього. У простому випадку, коли нам завжди доводиться додавати один нуль, paste0це найкраще рішення.

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

У випадку, коли в цифрах є змінна кількість цифр, ви повинні вручну обчислити, скільки нулів потрібно зробити передбачуваним, що досить жахливо, що ви повинні робити це лише з хворобливої ​​цікавості.


str_padвід stringrтворів, аналогічних до paste, що робить більш чітким, що ви хочете прокладати речі.

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

Знову ж таки, він насправді не призначений для використання з номерами, тому складніший випадок вимагає трохи подумати. Ми повинні просто мати можливість сказати "колодка з нулями до ширини 8", але подивіться на цей вихід:

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

Потрібно встановити варіант наукового штрафу таким чином, щоб цифри завжди форматувалися за допомогою фіксованих позначень (а не наукових позначень).

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

stri_padу stringiтворах точно так само, як і str_padз stringr.


formatCявляє собою інтерфейс для функції C printf. Для його використання потрібні певні знання аркани цієї основної функції (див. Посилання). У цьому випадку важливими моментами є widthаргумент, який formatє "d"для "цілого числа", а "0" flagдля попередніх нулів.

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"

Це моє улюблене рішення, оскільки легко повозитися зі зміною ширини, а функція досить потужна, щоб вносити інші зміни форматування.


sprintfє інтерфейсом до однойменної функції C; як, formatCале з іншим синтаксисом.

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

Основна перевага sprintfполягає в тому, що ви можете вставляти відформатовані номери у довші біти тексту.

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

Дивіться також відповідь Goodside .


Для повноти варто згадати інші функції форматування, які періодично корисні, але не мають методу попередження нулів.

format, загальна функція для форматування будь-якого виду об'єктів із методом числення. Це працює трохи схоже formatC, але з ще одним інтерфейсом.

prettyNum- це ще одна функція форматування, в основному для створення ручних міток для осі. Це особливо добре працює для широкого діапазону чисел.

scalesПакет має кілька функцій , такі як percent, date_formatі dollarдля фахівців типів форматів.


3
дякую за велику допомогу. Я використовував formatC, щоб додати до анімації провідні нулі, і це добре працювало.
baz

2
formatC (число або вектор, ширина = 6, формат = "d", прапор = "0") спрацював добре (R версія 3.0.2 (2013-09-25)). Дякую.
Мохамад Факих

1
використання formatC () описаним вище способом не працювало для мене. Він додав пробіли замість нулів. Я щось не так зробив? Я використовую R версії 3.1.1.
користувач1816679

2
@ user1816679 Звучить так, що ви забули flag = "0".
Річі Коттон

1
Розділ «Подробиці» на ?sprintfдовідковій сторінці описує це. "mn: два числа, розділені точкою, що позначають ширину поля (m) та точність (n)."
Річі Коттон

215

Для загального рішення, яке працює незалежно від кількості цифр data$anim, використовуйте sprintfфункцію. Це працює так:

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

У вашому випадку ви, мабуть, хочете: data$anim <- sprintf("%06d", data$anim)


14
Зверніть увагу, що sprintfперетворює числовий рядок (символ).
aL3xa

Дякую за відповідь. Я хочу зробити 13-розрядне число до 14-розрядного (додаючи провідний нуль). Здається, ця функція не працює в цьому випадку. Це дає мені помилку: Помилка sprintf ("% 020d", 4000100000104): недійсний формат '% 020d'; використовуйте формат% f,% e,% g або% a для числових об'єктів. Будь-яка пропозиція?
Rotail

Спробуйте: sprintf ("% 014.0f", 4000100000104)
Стюарт Макдональд

sprintf недоступний для R 3.4.1
Frank FYC

Так. Це не змінилося з версії 1.5.0.
dash2

33

Розширення на репсис @ goodside:

У деяких випадках ви можете прокласти рядок з нулями (наприклад, коди фіксації або інші числові фактори). В OSX / Linux:

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

Але через sprintf()те, що викликує sprintf()команду C ОС , про яку йдеться тут , у Windows 7 ви отримуєте інший результат:

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

Отже, на машинах Windows робота навколо:

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

1
З будь-якої причини це рішення більше не працює для мене в Linux. @ kdauria's str_padтепер мій піти.
metasequoia

25

str_padз stringrпакета - альтернатива.

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

4
Будьте дуже обережні, str_padоскільки це може призвести до несподіваних результатів. i.num = 600000; str_pad(i.num, width = 7, pad = "0") дасть вам "006e + 05", а не "0600000"
Панкіл Шах

2

Ось узагальнююча основна функція 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)

Мені подобається, sprintfале він поставляється із застереженнями:

однак реальна реалізація буде відповідати стандарту C99, а детальні деталі (особливо поведінка під помилкою користувача) можуть залежати від платформи


1

Ось ще одна альтернатива для додавання ведучих до 0 до рядків, таких як CUSIP, які іноді можуть бути схожими на число і які багато додатків, таких як Excel, пошкодять і видалять ведучі 0 або перетворять їх у наукові позначення.

Коли я спробував відповідь, надану @metasequoia, повернувся вектор мав провідні пробіли, а не 0s. Це була та сама проблема, яку згадував @ user1816679 - і вилучення лапок навколо 0або перехід на %dдо %sтакож не вплинуло . FYI, я використовую сервер RStudio, який працює на сервері Ubuntu. Це маленьке двоетапне рішення працювало для мене:

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

за допомогою функції %>%труби з magrittrпакету це може виглядати так:

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

Я вважаю за краще однофункціональне рішення, але воно працює.



0

Для інших обставин, за яких потрібно, щоб рядок чисел був послідовним, я створив функцію.

Хтось може вважати це корисним:

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)

Вибачте за форматування.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.