1

Data:

A            B
"2058600192", "2058644"
"4087600101", "4087601"
"30138182591","30138011"

I am trying to add one leading 0 to columns A and B if column A is 10 characters.

This is what I have written so far:

for (i in 1:nrow(data)) {
    if (nchar(data$A[i]) == 10) {  
      data$A[i] <- paste0(0, data$A)
      data$B[i] <- paste0(0, data$B)  
    } 
}

But I'm getting the following warning:

  number of items to replace is not a multiple of replacement length

I've also tried using a dplyr solution, but I'm not sure how to mutate two columns based on one column. Any insight would be appreciated.

Steffen Moritz
  • 7,277
  • 11
  • 36
  • 55
user12310746
  • 279
  • 1
  • 10
  • 1
    For your `for` loop to work, you should subset the `A` value on RHS as well. `paste0(0, data$A[i])` and same for `B`. Currently, you are replacing all the values of `A` in one value. – Ronak Shah Sep 01 '20 at 01:51

5 Answers5

1

You can get the index where the number of characters is equal to 10 and replace those values using lapply for multiple columns.

inds <- nchar(df$A) == 10
df[] <- lapply(df, function(x) replace(x, inds, paste0('0', x[inds])))
#If you want to replace only specific columns
#df[c('A', 'B')] <- lapply(df[c('A', 'B')], function(x) 
#                         replace(x, inds, paste0('0', x[inds])))
df

#            A        B
#1 02058600192 02058644
#2 04087600101 04087601
#3 30138182591 30138011

data

df <- structure(list(A = c(2058600192, 4087600101, 30138182591), B = c(2058644L, 
4087601L, 30138011L)), class = "data.frame", row.names = c(NA, -3L))
Ronak Shah
  • 377,200
  • 20
  • 156
  • 213
1

Your solution was already pretty good. You just made some very small mistakes. This code would give the correct output:

data <- data.frame(A = c("2058600192","4087600101","30138182591"), B = c("2058644","4087601","30138011"))

for (i in 1:nrow(data)) {
  
  if (nchar(data$A[i]) == 10) {
    
    data$A[i] <- paste0(0, data$A[i])
    data$B[i] <- paste0(0, data$B[i])
    
  } 
}

The only difference is data$A[i] <- paste0(0, data$A[i]) instead of data$A[i] <- paste0(0, data$A). Without the [i] you would try to add the whole column.

Steffen Moritz
  • 7,277
  • 11
  • 36
  • 55
1

Just in case you were interested in using dplyr here's another solution using transmute.

df %>%
  # Need to transmute B first, so that nchar is evaluated on the original A column and not on the one with leading zeros
  transmute(B = ifelse(nchar(A) == 10, paste0(0, B), B),
            A = ifelse(nchar(A) == 10, paste0(0, A), A)) %>%
  # Just change the order of the columns to the original one
  select(A,B)
1

Another way you can try

library(dplyr)
library(stringr)
df %>% 
  mutate(A = ifelse(str_length(A) == 10, str_pad(A, width = 11, side = "left", pad = 0), A),
         B = ifelse(grepl("^0", A), paste0("0", B), B))
#       A        B
# 1 02058600192 02058644
# 2 04087600101 04087601
# 3 30138182591 30138011
  • str_length to detect length of string
  • You can use str_pad to add leading zeros. More information about str_pad() here
  • We can use grepl to detect strings with leading zeros in column A and add leading zeros to column B.
Tho Vu
  • 1,304
  • 2
  • 8
  • 20
0

You may use the ifelse vectorized function here:

data$A <- ifelse(nchar(data$A) == 10, paste0("0", data$A), data$A)
data$B <- ifelse(nchar(data$B) == 10, paste0("0", data$B), data$B)
data

            A        B
1 02058600192  2058644
2 04087600101  4087601
3 30138182591 30138011
Tim Biegeleisen
  • 502,043
  • 27
  • 286
  • 360