Добавление ведущих нулей с помощью 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


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

675   8  

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 это еще одна функция форматирования, в основном для создания меток тиков оси вручную. Он работает особенно хорошо для широких диапазонов числа.

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

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

расширение на @ goodside repsonse:

в некоторых случаях вы можете заполнить строку нулями (например, коды 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 до %s тоже не имеет значения. К вашему сведению, я использую сервер 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 и мелкие детали (особенно поведение при ошибке пользователя) могут зависеть от платформы

Comments

    Ничего не найдено.