Добавление ведущих нулей с помощью R

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

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 ответов


короткая версия: используйте 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 с нулями ширина 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. Использование его требует некоторого знания арканы этой базовой функции (см. ссылку). В этом случае важными моментами являются , format будучи "d" для "integer" и A "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 для специализированных форматов.


общее решение, которое работает независимо от того, сколько цифр в data$anim используйте


расширение на repsonse @goodside это:

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

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

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

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

так что на машинах Windows работа вокруг:

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

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

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

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

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

когда я попробовал ответ, предоставленный @metasequoia, вектор вернулся с ведущими пробелами, а не 0s. Это была та же проблема, упомянутая @user1816679 -- и удаление кавычек вокруг 0 или изменение от %d to %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 = .)

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


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

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

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)

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


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