In einem großen Datenrahmen ("myfile") mit vier Spalten muss ich eine fünfte Spalte mit Werten hinzufügen, die bedingt auf den ersten vier Spalten basieren.
Bevorzugen Sie Antworten mit dplyr
und mutate
, hauptsächlich wegen der Geschwindigkeit in großen Datenmengen.
Mein Datenrahmen sieht folgendermaßen aus:
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
...
Die Werte der fünften Spalte (V5) basieren auf einigen bedingten Regeln:
if (V1==1 & V2!=4) {
V5 <- 1
} else if (V2==4 & V3!=1) {
V5 <- 2
} else {
V5 <- 0
}
Jetzt möchte ich die mutate
Funktion verwenden, um diese Regeln für alle Zeilen zu verwenden (um langsame Schleifen zu vermeiden). So etwas (und ja, ich weiß, dass es so nicht funktioniert!):
myfile <- mutate(myfile, if (V1==1 & V2!=4){V5 = 1}
else if (V2==4 & V3!=1){V5 = 2}
else {V5 = 0})
Dies sollte das Ergebnis sein:
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
Wie geht das dplyr
?
NA
, (NaN, +Inf, -Inf
)?dplyr
, dann würde ich besser verwendendata.table
.Antworten:
Versuche dies:
myfile %>% mutate(V5 = (V1 == 1 & V2 != 4) + 2 * (V2 == 4 & V3 != 1))
Geben:
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
oder dieses:
myfile %>% mutate(V5 = ifelse(V1 == 1 & V2 != 4, 1, ifelse(V2 == 4 & V3 != 1, 2, 0)))
Geben:
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
Hinweis
Schlagen Sie vor, dass Sie einen besseren Namen für Ihren Datenrahmen erhalten. myfile lässt es so aussehen, als ob es einen Dateinamen enthält.
Oben verwendet diese Eingabe:
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"))
Update 1 Da ursprünglich dplyr geändert wurde
%.%
, wurde%>%
die Antwort entsprechend geändert.Update 2 dplyr hat jetzt
case_when
eine andere Lösung:myfile %>% mutate(V5 = case_when(V1 == 1 & V2 != 4 ~ 1, V2 == 4 & V3 != 1 ~ 2, TRUE ~ 0))
quelle
ifelse
Aussagen nicht zu verschachteln :myfile %>% mutate(V5 = ifelse(V1 == 1 & V2 != 4, 1, 0), V5 = ifelse(V2 == 4 & V3 != 1, 2, V5))
Mit
dplyr 0.7.2
können Sie die sehr nützlichecase_when
Funktion verwenden: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)
Ausgedrückt mit
dplyr::mutate
gibt es:x = x %>% mutate( V5 = case_when( V1==1 & V2!=4 ~ 1, V2==4 & V3!=1 ~ 2, TRUE ~ 0 ) )
Bitte beachten Sie, dass diese
NA
nicht speziell behandelt werden, da dies irreführend sein kann. Die Funktion wirdNA
nur zurückgegeben, wenn keine Bedingung erfüllt ist. Wenn SieTRUE ~ ...
wie in meinem Beispiel eine Zeile mit setzen , wird der Rückgabewert dann niemals seinNA
.Daher müssen Sie ausdrücklich angeben
case_when
,NA
wo es hingehört, indem Sie eine Anweisung wie hinzufügenis.na(x$V1) | is.na(x$V3) ~ NA_integer_
. Hinweis: Diedplyr::coalesce()
Funktion kann hier manchmal sehr nützlich sein!Darüber hinaus beachten Sie bitte , dass
NA
allein in der Regel nicht arbeiten, müssen Sie besondere setzenNA
Werte:NA_integer_
,NA_character_
oderNA_real_
.quelle
Es sieht so
derivedFactor
aus, als ob dasmosaic
Paket dafür entworfen wurde. In diesem Beispiel würde es ungefähr so aussehen:library(mosaic) myfile <- mutate(myfile, V5 = derivedFactor( "1" = (V1==1 & V2!=4), "2" = (V2==4 & V3!=1), .method = "first", .default = 0 ))
(Wenn Sie möchten, dass das Ergebnis anstelle eines Faktors numerisch ist, schließen Sie das
derivedFactor
mit einemas.numeric
.)Beachten Sie, dass die
.default
Option in Kombination mit.method = "first"
die Bedingung "else" festlegt. Dieser Ansatz wird in der Hilfedatei für beschriebenderivedFactor
.quelle
.asFactor = F
Option oder die (ähnliche)derivedVariable
Funktion im selben Paket verwenden.recode
aus, als würde dplyr 0.5 dies tun. Ich habe es aber noch nicht untersucht. Siehe blog.rstudio.org/2016/06/27/dplyr-0-5-0mosaic::derivedFactor
Funktionsfamilie ist sehr langsam. Wenn Sie herausfinden, warum, beantworten Sie bitte meine SO-Frage dazu: stackoverflow.com/questions/33787691/… . Ich bin froh, dass Ihr anderer Kommentardplyr::case_when
schneller ist - ich muss darauf umsteigen.