2015-12-01 8 views
8

Mam serię nazw kolumn, które próbuję standaryzować.Dodawanie zer wiodących w ciągu znaków

names <- c("apple", "banana", "orange", "apple1", "apple2", "apple10", "apple11", "banana2", "banana12") 

pragnę niczego, co ma numer jeden cyfrowy być usztywniony przez zero, więc

apple 
banana 
orange 
apple01 
apple02 
apple10 
apple11 
banana02 
... 

Próbowałem użyć stringr

strdouble <- str_detect(names, "[0-9]{2}") 
strsingle <- str_detect(names, "[0-9]") 

str_detect(names[strsingle & !strdouble]) 

ale niezdolny do dowiedzieć się, jak selektywnie zastąpić/przed ...

+3

Czy 'sub (" ([a-z]) ([0-9]) $ "," \\ 10 \\ 2 ", nazwy)' pomóc? – etienne

+0

@etienne yes! Czy możesz wyjaśnić konstrukcję "\\ 10 \\ 2" dla wymiany? – ano

+0

Dodałem odpowiedź z wyjaśnieniem. – etienne

Odpowiedz

8

Można użyć sub("([a-z])([0-9])$","\\10\\2",names):

[1] "apple" "banana" "orange" "apple01" "apple02" "apple10" "apple11" "banana02" 
[9] "banana12" 

Zmienia się tylko imiona gdzie istnieje pojedyncza cyfra wyniku pisma (The $ jest koniec łańcucha).

Numer \\1 wybiera pierwszy blok w (): literę. Następnie umieszcza wiodący 0, a następnie drugi blok w (): cyfrę.

6

Oto jedna opcja z negatywnym Twierdzenia wyprzedzające i niedozwolone w celu identyfikacji pojedynczych cyfr.

gsub('(?<!\\d)(\\d)(?!\\d)', '0\\1', names, perl=TRUE) 
# [1] "apple" "banana" "orange" "apple01" "apple02" "apple10" "apple11" "banana02" "banana12" 
1

str_pad z stringr:

library(stringr) 

pad_if = function(x, cond, n, fill = "0") str_pad(x, n*cond, pad = fill) 

s = str_split_fixed(names,"(?=\\d)",2) 
#  [,1]  [,2] 
# [1,] "apple" "" 
# [2,] "banana" "" 
# [3,] "orange" "" 
# [4,] "apple" "1" 
# [5,] "apple" "2" 
# [6,] "apple" "10" 
# [7,] "apple" "11" 
# [8,] "banana" "2" 
# [9,] "banana" "12" 

paste0(s[,1], pad_if(s[,2], cond = nchar(s[,2]) > 0, n = max(nchar(s[,2])))) 
# [1] "apple" "banana" "orange" "apple01" "apple02" "apple10" "apple11" "banana02" "banana12" 

ta rozciąga się również do przypadków, jak będzie z c("a","a2","a20","a202") do c("a","a002","a020","a202"), których inne metody nie obejmują.

Pakiet stringr oparty jest na stringi, który ma tę samą funkcjonalność, co tutaj, zgaduję.


sprintf od podstawy, W podobny sposób:

pad_if2 = function(x, cond, n, fill = "0") 
    replace(x, cond, sprintf(paste0("%",fill,n,"d"), as.numeric(x)[cond])) 

s0 = strsplit(names,"(?<=\\D)(?=\\d)|$",perl=TRUE) 

s1 = sapply(s0,`[`,1) 
s2 = sapply(sapply(s0,`[`,-1), paste0, "") 

paste0(s1, pad_if2(s2, cond = nchar(s2) > 0, n = max(nchar(s2)))) 

pad_if2 mniej ogólne zastosowanie niż pad_if, ponieważ wymaga x być coercible numerycznego. Prawie każdy krok tutaj jest bardziej zwarty niż odpowiedni kod z wyżej wymienionymi pakietami.

+0

Pójdę naprzód i usuń to, jeśli sprawa zostanie wyjaśniona ... – Frank

0

Klucz służy do identyfikacji pojedynczej cyfry za pomocą $ i litery przed cyfrą. Można spróbować:

gsub('[^0-9]([0-9])$','0\\1',names) 
[1] "apple" "banana" "orange" "appl01" "appl02" "apple10" "apple11" "banan02" "banana12" 

lub z wyprzedzeniem.

gsub('(?<=[a-z])(\\d)$','0\\1',names,perl=T) 
+0

To samo, co Matthew, ale z '$' zamiast '(?! \\ d)'? Hmm, myślę, że bardziej przypomina combo z Matthew i Etienne'a ... – Frank