J'ai un bloc de données de numéros d'identification et je souhaite ajouter un suffixe basé sur une condition spécifique.
ID
+----------+ | ID | +----------+ | 130239_1 | | 130241_1 | | 130244_1 | | 130250_2 | | 130313_2 | | 130248_2 | | 130308_3 | +----------+
Essentiellement, s'il n'y a pas de _ dans le numéro d'identification, je veux ajouter le suffixe _1 , pour désigner l'échantillon 1. Si _ est présent, je ne souhaite pas qu'une action soit entreprise.
J'ai essayé d'écrire une instruction if-else combinée à un argument grepl, dans une boucle afin que je puisse appliquer l'instruction if-else à chaque ID individuellement:
Warning message:
In if (grepl("_", value)) { :
the condition has length > 1 and only the first element will be used
3 Réponses :
Nous pouvons créer un index logique basé sur l'occurrence de _ . Nier (! ), sous-définir la colonne 'ID' et coller le suffixe _1 et attribuer les valeurs à la colonne
df1 <- structure(list(ID = c("130239", "130241", "130244", "130250_2",
"130313_2", "130248_2", "130308_3")), class = "data.frame",
row.names = c(NA, -7L))
Avec grepl , nous ne modifions qu'une partie de la colonne. Serait utile en particulier lorsqu'il s'agit de grands ensembles de données
L'avertissement est que le code d'OP est basé sur l'utilisation de if / else qui n'est pas vectorisé. Pour cela, nous pouvons utiliser ifelse
i1 <- !grepl("_", df1$ID)
df1$ID[i1] <- paste0(df1$ID[i1], "_1")
df1
# ID
#1 130239_1
#2 130241_1
#3 130244_1
#4 130250_2
#5 130313_2
#6 130248_2
#7 130308_3
Merci, akrun pour une belle solution. Je comprends la première ligne: vous appliquez un opérateur logique à tous les ID qui ne contiennent pas _ . Ai-je raison de dire que la deuxième ligne ajoute _1 pour chaque valeur TRUE dans i1 ? Je suis également confus au sujet de la deuxième ligne: est-ce que le 0 après paste doit être présent si vous ajoutez le suffixe _1 ? Il semble que cela fonctionne toujours avec paste seul, mais je veux m'assurer de ne pas manquer quelque chose de conceptuel. Merci.
@EdmondKwan En ce qui concerne votre premier point, oui, avec grepl il vérifie le motif _ , puis faites la négation (! ) TRUE-> FALSE et viiceversa. Utilisez cet index pour filtrer l'ID sans avoir le _ puis avec paste ( paste0 avoir sep = "" code> tandis que paste ont sep = '") c'est la différence. Vous pouvez consulter la documentation de ? paste0
Vous pouvez utiliser gsub () et des expressions régulières. S'il y a trois chiffres consécutifs ou plus à la fin, il ajoutera un "_1".
df1 <- structure(list(ID = structure(c(1L, 2L, 3L, 5L, 7L, 4L, 6L), .Label = c("130239",
"130241", "130244", "130248_2", "130250_2", "130308_3", "130313_2"
), class = "factor")), class = "data.frame", row.names = c(NA,
-7L))
Données strong>
df1 <- gsub(".*?(\\d{3,})$", "\\1_1", df1$ID)
df1
# [1] "130239_1" "130241_1" "130244_1" "130250_2" "130313_2" "130248_2" "130308_3"
Une seule ligne utilisant la fonction anonyme, Filter et grepl.
df1 <- structure(list(ID = c("130239", "130241", "130244", "130250_2",
"130313_2", "130248_2", "130308_3")), class = "data.frame",
row.names = c(NA, -7L))
Cela aussi peut produire un résultat similaire. p >
df1[df1$ID %in% df1[!grepl("\\_", df1$ID), ],] <- paste(df1[df1$ID %in% df1[!grepl("\\_", df1$ID), ],], "_1", sep ="")
# ID
# 1 130239_1
# 2 130241_1
# 3 130244_1
# 4 130250_2
# 5 130313_2
# 6 130248_2
# 7 130308_3
df1[df1$ID %in% (Filter(function(x) !grepl("\\_", x), df1$ID)),] <- paste(df1[df1$ID %in% (Filter(function(x) !grepl("\\_", x), df1$ID)),], "_1", sep ="")
# ID
# 1 130239_1
# 2 130241_1
# 3 130244_1
# 4 130250_2
# 5 130313_2
# 6 130248_2
# 7 130308_3