2017-11-23 14 views
0

Ich versuche, eine neue Spalte basierend auf den Werten anderer Spalten zu erstellen.R: muate über mehrere Spalten, um eine neue Spalte zu erstellen

Hier ist ein Datensatz, der dem ähnelt, woran ich gerade arbeite. Ich habe drei Variablen, Test1, Test2, Test3. Ich versuche eine neue Variable zu erstellen, die 1 ist, wenn eine der Testvariablen entweder DF60, DF61, DF63 oder DF64 oder 0 ist.

Test1<-c("DF64", "DF63", "DF89", "DF30", "DF70") 
Test2<-c("DF61", "DF25", "DF00", "DF30", "DF99") 
Test3<-c("DF80", "DF63", "DF60", "DF63", "DF70") 
Test<-data.frame(Test1, Test2, Test3) 

Ich habe viele ifelse Aussagen im Moment und bin auf der Suche nach einem Code, der Schleife über die mehrere Testvariablen können, während mehrere Werte erlaubt nachgeschlagen werden.

Nachdem ich einige ähnliche Threads durchgesehen habe, habe ich mutate_at versucht, aber ich denke nicht, dass das der richtige Weg ist.

Test2<- Test %>% 
mutate_at(vars(starts_with("Test")), funs(Test=ifelse("DF60" | "DF61" | 
"DF62" | "DF63", 1, 0))) 

Jede Hilfe wird sehr geschätzt!

Danke!

Antwort

1
Test2<- Test %>% 
dplyr::select(starts_with("Test"))%>% 
mutate_all(function(x){x %in% c("DF60","DF61","DF62","DF63")})%>% 
mutate(out = ifelse(rowSums(.)<1,0,1)) 

Adjustment nach Kommentar

Wenn Sie andere Spalten behalten möchten, mutate_at, wie yutannihilation vorgeschlagen wird, ist viel besser. Das Problem besteht dann darin, die Zeilenumbrüche bei einer Auswahl der Spalten mutieren zu lassen.

library(tidyverse) 
library(anomalyDetection) 

Test1<-c("DF64", "DF63", "DF89", "DF30", "DF70") 
Test2<-c("DF61", "DF25", "DF00", "DF30", "DF99") 
Test3<-c("DF80", "DF63", "DF60", "DF63", "DF70") 
Test<-data.frame(Test1, Test2, Test3) 

Test$ExtraCol<-LETTERS[1:5] 


Test2<- Test %>% 
    mutate_at(vars(starts_with("Test")),funs(bin=.%in% c("DF60","DF61","DF62","DF63")))%>% 
    split(.,1<10)%>% 
    map_df(~mutate(.,out=rowSums(.[paste0("Test",1:3,"_bin")])>0)) 


    Test1 Test2 Test3 ExtraCol Test1_bin Test2_bin Test3_bin out 
    DF64 DF61 DF80  A  FALSE  TRUE  FALSE TRUE 
    DF63 DF25 DF63  B  TRUE  FALSE  TRUE TRUE 
    DF89 DF00 DF60  C  FALSE  FALSE  TRUE TRUE 
    DF30 DF30 DF63  D  FALSE  FALSE  TRUE TRUE 
    DF70 DF99 DF70  E  FALSE  FALSE  FALSE FALSE 
+0

Danke! Gibt es eine Möglichkeit, alle ursprünglichen Variablen beizubehalten (gibt es andere Variablen zusätzlich zu Test1, Test2, Test3)? Ich muss mehrere Variablen basierend auf den gleichen Test1, Test2, Tes3 Variablen erstellen, so dass sie nicht geändert werden sollen. – user3047435

+0

Danke !!! Tut mir leid, was macht Split (., 1 <10) in diesem Fall? – user3047435

+0

split teilt das df in eine Liste von dfs basierend auf dem Argument auf. Das folgende map_df wendet das Argument auf jedes dieser dfs an und bindet sie zurück in ein df.In diesem Fall wollte ich keine Liste verschiedener dfs, sondern nur eine Liste von einem df (dem ganzen df). Deshalb teile ich basierend auf einem Argument, das immer wahr ist (nicht sicher, ob es notwendig ist, du könntest ohne versuchen. Diese Antwort basiert auf einer vorherigen Frage von mir auf stackoverflow. Wenn du dem Link folgst, wirst du sehen, woher der Split kommt) – Dries

1

Während Dries Antwort schön genug ist, lassen Sie mich eine Erklärung über funs() hinzufügen: Keine Ahnung, ob das nächste, was am besten Praxis ist, aber es funktioniert (dplyr mutate on column subset (one function on all these columns combined) eine Antwort auf eine frühere Anfrage von mir überarbeitet).

funs() nimmt Paare von Suffix und Ausdruck. wenn Sie suffix1 und suffix2 zum Beispiel angeben, werden Sie neue Spalten erhalten genannt Test1_suffix1, Test1_suffix2, Test2_suffix1, Test2_suffix2 und so weiter:

funs(suffix1 = ..., suffix2 = ...) 

Zweitens müssen Sie . einen Spaltenvektor darstellen. So sollte die richtige Version Ihrer ifelse(...) wie:

Test %>% 
    mutate_at(vars(starts_with("Test")), 
      funs(bin = ifelse(. == "DF60" | . == "DF61" | . == "DF62" | . == "DF63", 1, 0))) 
#> Test1 Test2 Test3 Test1_bin Test2_bin Test3_bin 
#> 1 DF64 DF61 DF80   0   1   0 
#> 2 DF63 DF25 DF63   1   0   1 
#> 3 DF89 DF00 DF60   0   0   1 
#> 4 DF30 DF30 DF63   0   0   1 
#> 5 DF70 DF99 DF70   0   0   0 

Offenbar %in% ist besser als Folge von |.

Test %>% 
    mutate_at(vars(starts_with("Test")), 
      funs(bin = ifelse(. %in% c("DF60", "DF61", "DF62", "DF63"), 1, 0))) 
#> Test1 Test2 Test3 Test1_bin Test2_bin Test3_bin 
#> 1 DF64 DF61 DF80   0   1   0 
#> 2 DF63 DF25 DF63   1   0   1 
#> 3 DF89 DF00 DF60   0   0   1 
#> 4 DF30 DF30 DF63   0   0   1 
#> 5 DF70 DF99 DF70   0   0   0 

Wenn Sie nur filtern möchten, können Sie filter_at() verwenden.

Test %>% 
    filter_at(vars(starts_with("Test")), 
      any_vars(. %in% c("DF60", "DF61", "DF62", "DF63"))) 
#> Test1 Test2 Test3 
#> 1 DF64 DF61 DF80 
#> 2 DF63 DF25 DF63 
#> 3 DF89 DF00 DF60 
#> 4 DF30 DF30 DF63 
Verwandte Themen