Dans une grande base de données ("monfichier") à quatre colonnes, je dois ajouter une cinquième colonne avec des valeurs conditionnellement basées sur les quatre premières colonnes.
Préférez les réponses avec dplyr
et mutate
, principalement en raison de sa rapidité dans les grands ensembles de données.
Mon cadre de données ressemble à ceci:
V1 V2 V3 V4
1 1 2 3 5
2 2 4 4 1
3 1 4 1 1
4 4 5 1 3
5 5 5 5 4
...
Les valeurs de la cinquième colonne (V5) sont basées sur des règles conditionnelles:
if (V1==1 & V2!=4) {
V5 <- 1
} else if (V2==4 & V3!=1) {
V5 <- 2
} else {
V5 <- 0
}
Maintenant, je veux utiliser la fonction mutate
pour utiliser ces règles sur toutes les lignes (pour éviter les boucles lentes). Quelque chose comme ça (et oui, je sais que ça ne marche pas comme ça!):
myfile <- mutate(myfile, if (V1==1 & V2!=4){V5 = 1}
else if (V2==4 & V3!=1){V5 = 2}
else {V5 = 0})
Cela devrait être le résultat:
V1 V2 V3 V4 V5
1 1 2 3 5 1
2 2 4 4 1 2
3 1 4 1 1 0
4 4 5 1 3 0
5 5 5 5 4 0
Comment faire cela dans dplyr
?
Essaye ça:
myfile %>% mutate(V5 = (V1 == 1 & V2 != 4) + 2 * (V2 == 4 & V3 != 1))
donnant:
V1 V2 V3 V4 V5
1 1 2 3 5 1
2 2 4 4 1 2
3 1 4 1 1 0
4 4 5 1 3 0
5 5 5 5 4 0
ou ca:
myfile %>% mutate(V5 = ifelse(V1 == 1 & V2 != 4, 1, ifelse(V2 == 4 & V3 != 1, 2, 0)))
donnant:
V1 V2 V3 V4 V5
1 1 2 3 5 1
2 2 4 4 1 2
3 1 4 1 1 0
4 4 5 1 3 0
5 5 5 5 4 0
Vous suggérons d’obtenir un meilleur nom pour votre bloc de données. myfile donne l'impression qu'il contient un nom de fichier.
Ci-dessus utilisé cette entrée:
myfile <-
structure(list(V1 = c(1L, 2L, 1L, 4L, 5L), V2 = c(2L, 4L, 4L,
5L, 5L), V3 = c(3L, 4L, 1L, 1L, 5L), V4 = c(5L, 1L, 1L, 3L, 4L
)), .Names = c("V1", "V2", "V3", "V4"), class = "data.frame", row.names = c("1",
"2", "3", "4", "5"))
Mise à jour 1 Depuis le premier post, dplyr a changé %.%
à %>%
ont donc modifié la réponse en conséquence.
Mise à jour 2 dplyr a maintenant case_when
qui fournit une autre solution:
myfile %>%
mutate(V5 = case_when(V1 == 1 & V2 != 4 ~ 1,
V2 == 4 & V3 != 1 ~ 2,
TRUE ~ 0))
Avec dplyr 0.7.2
, Vous pouvez utiliser la fonction très utile case_when
:
x=read.table(
text="V1 V2 V3 V4
1 1 2 3 5
2 2 4 4 1
3 1 4 1 1
4 4 5 1 3
5 5 5 5 4")
x$V5 = case_when(x$V1==1 & x$V2!=4 ~ 1,
x$V2==4 & x$V3!=1 ~ 2,
TRUE ~ 0)
Exprimé avec dplyr::mutate
, Il donne:
x = x %>% mutate(
V5 = case_when(
V1==1 & V2!=4 ~ 1,
V2==4 & V3!=1 ~ 2,
TRUE ~ 0
)
)
Veuillez noter que NA
ne sont pas traités spécialement, cela peut être trompeur. La fonction ne retournera NA
que si aucune condition ne correspond. Si vous mettez une ligne avec TRUE ~ ...
, Comme je l'ai fait dans mon exemple, la valeur de retour ne sera alors jamais NA
.
Par conséquent, vous devez explicitement dire à case_when
De mettre NA
à quoi il appartient en ajoutant une instruction comme is.na(x$V1) | is.na(x$V3) ~ NA_integer_
. Astuce: la fonction dplyr::coalesce()
peut être très utile ici parfois!
De plus, notez que NA
seul ne fonctionnera généralement pas, vous devez mettre des valeurs spéciales NA
: NA_integer_
, NA_character_
Ou NA_real_
.
Il semble que derivedFactor
du package mosaic
ait été conçu pour cela. Dans cet exemple, cela ressemblerait à quelque chose comme:
library(mosaic)
myfile <- mutate(myfile, V5 = derivedFactor(
"1" = (V1==1 & V2!=4),
"2" = (V2==4 & V3!=1),
.method = "first",
.default = 0
))
(Si vous voulez que le résultat soit numérique au lieu d’un facteur, enveloppez le derivedFactor
avec un as.numeric
.)
Notez que le .default
option combinée avec .method = "first"
définit la condition "else" - cette approche est décrite dans le fichier d'aide de derivedFactor
.