Les données:

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

J'essaye d'ajouter un 0 menant aux colonnes A et B si la colonne A est de 10 caractères.

Voici ce que j'ai écrit jusqu'à présent:

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)  
    } 
}

Mais je reçois l'avertissement suivant:

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

J'ai également essayé d'utiliser une solution dplyr, mais je ne suis pas sûr de savoir comment muter deux colonnes en fonction d'une colonne. Tout aperçu serait apprécié.

1
user12310746 1 sept. 2020 à 04:42

5 réponses

Meilleure réponse

Votre solution était déjà assez bonne. Vous venez de faire de très petites erreurs. Ce code donnerait la sortie correcte:

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])
    
  } 
}

La seule différence est data$A[i] <- paste0(0, data$A[i]) au lieu de data$A[i] <- paste0(0, data$A). Sans le [i], vous essayez d'ajouter la colonne entière.

1
Steffen Moritz 1 sept. 2020 à 01:56

Vous pouvez utiliser la fonction vectorisée ifelse ici:

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
0
Tim Biegeleisen 1 sept. 2020 à 01:46

Juste au cas où vous seriez intéressé à utiliser dplyr, voici une autre solution utilisant 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
Jonathan V. Solórzano 1 sept. 2020 à 02:00

Vous pouvez obtenir l'index où le nombre de caractères est égal à 10 et replace ces valeurs en utilisant lapply pour plusieurs colonnes.

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

données

df <- structure(list(A = c(2058600192, 4087600101, 30138182591), B = c(2058644L, 
4087601L, 30138011L)), class = "data.frame", row.names = c(NA, -3L))
1
Ronak Shah 1 sept. 2020 à 01:47

Une autre façon d'essayer

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 pour détecter la longueur de la chaîne
  • Vous pouvez utiliser str_pad pour ajouter des zéros non significatifs. Plus d'informations sur str_pad() ici
  • Nous pouvons utiliser grepl pour détecter les chaînes avec des zéros non significatifs dans la colonne A et ajouter des zéros non significatifs à la colonne B.
1
Tho Vu 2 sept. 2020 à 01:24