Как добавить ведущие нули? - PullRequest
303 голосов
/ 28 апреля 2011

У меня есть набор данных, который выглядит примерно так:

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

И ради интереса, что если мне нужно добавить два или три нуля до идентификатора животного?

Ответы [ 8 ]

481 голосов
/ 28 апреля 2011

Короткая версия: используйте 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"

Опять же, он на самом деле не предназначен для использования с числами, поэтому в более сложном случае нужно немного подумать. Мы должны просто иметь возможность сказать «pad with zeroes to width 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." 

См. Также ответ товара .


Для полноты картины стоит упомянуть другие функции форматирования, которые иногда полезны, но не имеют метода добавления нулей.

format, универсальная функция для форматирования любого типа объекта, с методом для чисел. Он работает немного как formatC, но с еще одним интерфейсом.

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

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

200 голосов
/ 28 апреля 2011

Для общего решения, которое работает независимо от того, сколько цифр в data$anim, используйте функцию sprintf.Это работает так:

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

В вашем случае вы, вероятно, захотите: data$anim <- sprintf("%06d", data$anim)

29 голосов
/ 21 августа 2013

Расширение по отклику @ goodside:

В некоторых случаях вы можете дополнить строку нулями (например, коды fips или другие числовые факторы).В OSX / Linux:

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

Но поскольку sprintf() вызывает команду ОС C sprintf(), обсуждаемую здесь , в Windows 7 вы получите другой результат:

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

Итак, на машинах с Windows обходной путь:

> sprintf("%05d", as.numeric("104"))
[1] "00104"
21 голосов
/ 27 августа 2014

str_pad из пакета stringr является альтернативой.

anim = 25499:25504
str_pad(anim, width=6, pad="0")
2 голосов
/ 27 сентября 2018

Вот обобщаемая базовая функция 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 имелкие детали (особенно поведение при ошибке пользователя) могут зависеть от платформы

2 голосов
/ 20 апреля 2016
data$anim <- sapply(0, paste0,data$anim)
1 голос
/ 03 апреля 2017

Для других обстоятельств, в которых вы хотите, чтобы числовая строка была последовательной, я сделал функцию.

Кто-то может найти это полезным:

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)

Извините за форматирование.

1 голос
/ 10 декабря 2016

Вот еще одна альтернатива для добавления ведущих к нулям в строки, такие как CUSIPs , которые иногда могут выглядеть как числа и которые многие приложения, такие как Excel, будут повреждать и удалять ведущие 0 или конвертировать их в научную нотацию ,

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

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

с использованием функции %>% pipe из пакета magrittr это может выглядеть так:

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

Я бы предпочел однофункциональное решение, но оно работает.

...