Dans un grand dataframe ("myfile") avec 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 dataframe 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 certaines 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 mutate
fonction 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 dplyr
?
NA
, (NaN, +Inf, -Inf
)?dplyr
, alors je ferais mieux de l'utiliserdata.table
.Réponses:
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
Remarque
Suggérez-vous 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 la publication initiale de dplyr a changé
%.%
pour%>%
donc avoir modifié la réponse en conséquence.La mise à jour 2 dplyr a maintenant
case_when
une autre solution:myfile %>% mutate(V5 = case_when(V1 == 1 & V2 != 4 ~ 1, V2 == 4 & V3 != 1 ~ 2, TRUE ~ 0))
la source
ifelse
déclarations:myfile %>% mutate(V5 = ifelse(V1 == 1 & V2 != 4, 1, 0), V5 = ifelse(V2 == 4 & V3 != 1, 2, V5))
Avec
dplyr 0.7.2
, vous pouvez utiliser lacase_when
fonction très utile :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 qu'ils
NA
ne sont pas traités spécialement, car cela peut être trompeur. La fonction ne sera renvoyéeNA
que si aucune condition ne correspond. Si vous mettez une ligne avecTRUE ~ ...
, comme je l'ai fait dans mon exemple, la valeur de retour ne sera alors jamaisNA
.Par conséquent, vous devez dire de manière expressive
case_when
de mettre àNA
sa place en ajoutant une instruction commeis.na(x$V1) | is.na(x$V3) ~ NA_integer_
. Astuce: ladplyr::coalesce()
fonction peut être vraiment utile ici parfois!De plus, s'il vous plaît noter que
NA
seuls travaillent habituellement pas, vous devez mettre spéciauxNA
valeurs:NA_integer_
,NA_character_
ouNA_real_
.la source
Il semble que
derivedFactor
lemosaic
package a é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 souhaitez que le résultat soit numérique au lieu d'un facteur, encapsulez le
derivedFactor
avec unas.numeric
.)Notez que l'
.default
option combinée avec.method = "first"
définit la condition "else" - cette approche est décrite dans le fichier d'aide pourderivedFactor
.la source
.asFactor = F
option ou en utilisant la fonction (similaire)derivedVariable
dans le même package.recode
dplyr 0.5 fera cela. Cependant, je n'ai pas encore enquêté dessus. Voir blog.rstudio.org/2016/06/27/dplyr-0-5-0mosaic::derivedFactor
famille de fonctions est très lente. Si vous comprenez pourquoi, veuillez répondre à ma question SO à ce sujet: stackoverflow.com/questions/33787691/… . Je suis heureux de voir d'après votre autre commentaire quedplyr::case_when
c'est plus rapide - je vais devoir passer à cela.