W dużej ramce danych („myfile”) z czterema kolumnami muszę dodać piątą kolumnę z wartościami warunkowo opartymi na pierwszych czterech kolumnach.
Preferuj odpowiedzi z dplyr
i mutate
, głównie ze względu na szybkość w dużych zbiorach danych.
Moja ramka danych wygląda następująco:
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
...
Wartości z piątej kolumny (V5) są oparte na pewnych regułach warunkowych:
if (V1==1 & V2!=4) {
V5 <- 1
} else if (V2==4 & V3!=1) {
V5 <- 2
} else {
V5 <- 0
}
Teraz chcę użyć mutate
funkcji, aby użyć tych reguł we wszystkich wierszach (aby uniknąć powolnych pętli). Coś takiego (i tak, wiem, że to nie działa!):
myfile <- mutate(myfile, if (V1==1 & V2!=4){V5 = 1}
else if (V2==4 & V3!=1){V5 = 2}
else {V5 = 0})
Powinien to być wynik:
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
Jak to zrobić w dplyr
?
NA
, (NaN, +Inf, -Inf
)?dplyr
, lepiej skorzystałbym zdata.table
.Odpowiedzi:
Spróbuj tego:
myfile %>% mutate(V5 = (V1 == 1 & V2 != 4) + 2 * (V2 == 4 & V3 != 1))
dający:
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
albo to:
myfile %>% mutate(V5 = ifelse(V1 == 1 & V2 != 4, 1, ifelse(V2 == 4 & V3 != 1, 2, 0)))
dający:
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
Uwaga
Zaproponuj lepszą nazwę ramki danych. myfile sprawia, że wygląda na to, że przechowuje nazwę pliku.
Powyżej użyłem tego wejścia:
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"))
Aktualizacja 1 Ponieważ pierwotnie opublikowano dplyr, zmienił się
%.%
na,%>%
więc odpowiednio zmodyfikował odpowiedź.Update 2 dplyr ma teraz
case_when
inne rozwiązanie:myfile %>% mutate(V5 = case_when(V1 == 1 & V2 != 4 ~ 1, V2 == 4 & V3 != 1 ~ 2, TRUE ~ 0))
źródło
ifelse
stwierdzeń:myfile %>% mutate(V5 = ifelse(V1 == 1 & V2 != 4, 1, 0), V5 = ifelse(V2 == 4 & V3 != 1, 2, V5))
Za pomocą
dplyr 0.7.2
możesz skorzystać z bardzo przydatnejcase_when
funkcji: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)
Wyrażony za pomocą
dplyr::mutate
daje:x = x %>% mutate( V5 = case_when( V1==1 & V2!=4 ~ 1, V2==4 & V3!=1 ~ 2, TRUE ~ 0 ) )
Należy pamiętać, że
NA
nie są one traktowane specjalnie, ponieważ mogą wprowadzać w błąd. Funkcja zwróciNA
tylko wtedy, gdy żaden warunek nie zostanie spełniony. Jeśli umieścisz linię zTRUE ~ ...
, tak jak w moim przykładzie, wartość zwracana nigdy nie będzieNA
.Dlatego musisz wyraźnie powiedzieć,
case_when
aby umieścićNA
tam, gdzie należy, dodając stwierdzenie takie jakis.na(x$V1) | is.na(x$V3) ~ NA_integer_
. Podpowiedź:dplyr::coalesce()
funkcja może się tu czasem przydać!Ponadto, należy pamiętać, że
NA
sam będzie zazwyczaj nie praca, trzeba umieścić specjalneNA
wartości:NA_integer_
,NA_character_
lubNA_real_
.źródło
Wygląda na to, że
derivedFactor
zmosaic
pakietu został zaprojektowany do tego. W tym przykładzie wyglądałoby to mniej więcej tak:library(mosaic) myfile <- mutate(myfile, V5 = derivedFactor( "1" = (V1==1 & V2!=4), "2" = (V2==4 & V3!=1), .method = "first", .default = 0 ))
(Jeśli chcesz, aby wynik był liczbowy zamiast współczynnika, zawiń
derivedFactor
goas.numeric
.)Zauważ, że
.default
opcja połączona z.method = "first"
ustawia warunek „else” - to podejście jest opisane w pliku pomocy dladerivedFactor
.źródło
.asFactor = F
opcji lub używając (podobnej)derivedVariable
funkcji w tym samym pakiecie.recode
dplyr 0.5 to zrobi. Jednak jeszcze tego nie zbadałem. Zobacz blog.rstudio.org/2016/06/27/dplyr-0-5-0mosaic::derivedFactor
rodzina funkcji działa bardzo wolno. Jeśli dowiesz się dlaczego, odpowiedz na moje pytanie SO dotyczące tego: stackoverflow.com/questions/33787691/… . Cieszę się, widząc po Twoim drugim komentarzu, którydplyr::case_when
jest szybszy - będę musiał się na to przełączyć.