2016-06-21 23 views
0

Unten sind zwei einfache Datenrahmen. Ich möchte die Spalten Sat1 und Sat2 neu codieren (zusammenfassen), so dass alle Grade von erfüllt sind einfach als Satisfied codiert, und alle Grade von Unzufrieden sind als Dissatisfied codiert. Neutral bleibt neutral. Diese Faktoren werden daher drei Ebenen haben: Satisfied, Dissatisfied, and Neutral.Umcodieren ähnlicher Faktorebenen über mehrere Datenrahmen hinweg mit Purrr und Dplyr

Ich würde normalerweise dies durch die Datenrahmen-Bindung und unter Verwendung von lapply zusammen mit Re-Code aus dem car Paket, wie zum Beispiel:

DF1[2:3] <- lapply(DF1[2:3], recode, c('"Somewhat Satisfied"= "Satisfied","Satisfied"="Satisfied","Extremely Dissatisfied"="Dissatisfied"........etc, etc 

Ich mag diese unter Verwendung von Kartenfunktionen erreichen, und zwar at_map (um den Datenrahmen zu pflegen, aber ich bin neu zu purrr so zögern Sie, andere Versionen der Karte vorzuschlagen) von purrr, sowie dplyr, tidyr , stringr and ggplot2` so kann alles leicht pipelined werden.

Das Beispiel unten ist das, was ich erreichen möchte, aber für die Umcodierung, aber ich konnte es nicht zum Laufen bringen.

http://www.r-bloggers.com/using-purrr-with-dplyr/

Ich würde so eine ähnliche Kartenfunktion nutzen möchten at_map oder dass ich die ursprünglichen Spalten von Sat1 halten können und Sat2, so dass die neu kodierten Spalten in den Datenrahmen und umbenannt werden hinzugefügt. Es wäre großartig, wenn dieser Schritt auch in einer Funktion enthalten wäre.

In Wirklichkeit werde ich viele Datenrahmen haben, also will ich nur die Faktorstufen einmal umcodieren und dann eine Funktion von purrr verwenden, um die Änderungen über alle Datenrahmen mit der geringsten Menge an Code vorzunehmen.

Names<-c("James","Chris","Jessica","Tomoki","Anna","Gerald") 
Sat1<-c("Satisfied","Very Satisfied","Dissatisfied","Somewhat Satisfied","Dissatisfied","Neutral") 
Sat2<-c("Very Dissatisfied","Somewhat Satisfied","Neutral","Neutral","Satisfied","Satisfied") 
Program<-c("A","B","A","C","B","D") 
Pets<-c("Snake","Dog","Dog","Dog","Cat","None") 

DF1<-data.frame(Names,Sat1,Sat2,Program,Pets) 

Names<-c("Tim","John","Amy","Alberto","Desrahi","Francesca") 
Sat1<-c("Extremely Satisfied","Satisfied","Satisfed","Somewhat Dissatisfied","Dissatisfied","Satisfied") 
Sat2<-c("Dissatisfied","Somewhat Dissatisfied","Neutral","Extremely Dissatisfied","Somewhat Satisfied","Somewhat Dissatisfied") 
Program<-c("A","B","A","C","B","D") 


DF2<-data.frame(Names,Sat1,Sat2,Program) 
+0

Möchten Sie alle Ihre Datenrahmen am Ende kombiniert oder in einer Liste getrennt gespeichert oder ...? Dies scheint ziemlich einfach zu sein, mit etwas wie "mutate_each" von dplyr_0.4.3.9000 kombiniert mit "map" oder "map_df". 'map_at' sieht so aus, als ob es die aktuellen Variablen ersetzt, daher ist es möglicherweise nicht das Werkzeug, das in diesem Fall verwendet wird. – aosmith

+0

Danke für Ihre Antwort. Ich nehme an, es ist in Ordnung, wenn die Datenrahmen in einer Liste getrennt bleiben. Mein Hauptziel ist es, einen schnellen Weg (innerhalb der purrr dplyr-Pipeline) zu finden, der es mir ermöglicht, die Faktoren über mehrere Datenrahmen gleichzeitig zu rekodieren. Ich mag die Idee, mutate_each und eine Kartenfunktion zu kombinieren. Es ist in Ordnung, wenn die aktuellen Variablen ersetzt werden, da ich zuerst die Datenrahmen kopieren kann. Ich wäre Ihnen dankbar, wenn Sie den Code für Ihr Beispiel zeigen könnten. – Mike

Antwort

1

Eine Möglichkeit, dies zu tun ist, mutate_each zu verwenden, um die Arbeit mit einem der map Funktionen kombiniert zu tun durch eine Liste von data.frames zu gehen. Mit mutate_each oder äquivalent von dplyr_0.4.3.9001 können Sie die neuen Spalten umbenennen.

In diesem Fall könnten Sie die Zeichenfolgenmanipulation anstelle der Umcodierung verwenden. Ich glaube, dass Sie Satisfied, Dissatisfied oder Neutral aus den aktuellen Strings ziehen möchten, die Sie haben. Sie können dies mit sub mithilfe von regulären Ausdrücken erreichen. Zum Beispiel

sub(".*(Satisfied|Dissatisfied|Neutral).*$", "\\1", DF2$Sat2) 
"Dissatisfied" "Dissatisfied" "Neutral"  "Dissatisfied" "Satisfied" "Dissatisfied" 

Paket stringr hat eine nette Funktion für bestimmte Zeichenfolgen zu extrahieren, str_extract.

library(stringr) 
str_extract(DF2$Sat2, "Satisfied|Neutral|Dissatisfied") 
"Dissatisfied" "Dissatisfied" "Neutral"  "Dissatisfied" "Satisfied" "Dissatisfied" 

Sie können dies innerhalb mutate_each verwenden eine dieser Funktionen auf mehrere Spalten zu verwenden. Der Name, den Sie für die Funktion innerhalb von funs angeben, wird den neuen Spaltennamen hinzugefügt. Ich habe recode verwendet.Für einen Ihrer Datensätze:

DF1 %>% 
    mutate_each(funs(recode = str_extract(., "Satisfied|Neutral|Dissatisfied")), 
       starts_with("Sat")) 

    Names    Sat1    Sat2 Program Pets Sat1_recode Sat2_recode 
1 James   Satisfied Very Dissatisfied  A Snake Satisfied Dissatisfied 
2 Chris  Very Satisfied Somewhat Satisfied  B Dog Satisfied Satisfied 
3 Jessica  Dissatisfied   Neutral  A Dog Dissatisfied  Neutral 
4 Tomoki Somewhat Satisfied   Neutral  C Dog Satisfied  Neutral 
5 Anna  Dissatisfied   Satisfied  B Cat Dissatisfied Satisfied 
6 Gerald   Neutral   Satisfied  D None  Neutral Satisfied 

Um durch viele Datensätze in einer Liste gespeichert, können Sie eine map Funktion von purrr verwenden, um eine Funktion auf jedes Element in der Liste auszuführen.

list(DF1, DF2) %>% 
    map(~mutate_each(.x, 
        funs(recode = str_extract(., "Satisfied|Neutral|Dissatisfied")), 
        starts_with("Sat"))) 

[[1]] 
    Names    Sat1    Sat2 Program Pets Sat1_recode Sat2_recode 
1 James   Satisfied Very Dissatisfied  A Snake Satisfied Dissatisfied 
2 Chris  Very Satisfied Somewhat Satisfied  B Dog Satisfied Satisfied 
... 
[[2]] 
     Names     Sat1     Sat2 Program Sat1_recode Sat2_recode 
1  Tim Extremely Satisfied   Dissatisfied  A Satisfied Dissatisfied 
2  John    Satisfied Somewhat Dissatisfied  B Satisfied Dissatisfied 
... 

Mit map_df stattdessen alle Elemente in Ihrer Liste in eine data.frame binden, die kann oder auch nicht sein, was Sie wollen. Mit dem Argument .id wird für jedes ursprüngliche Dataset ein Name hinzugefügt.

list(DF1, DF2) %>% 
    map_df(~mutate_each(.x, 
        funs(recode = str_extract(., "Satisfied|Neutral|Dissatisfied")), 
        starts_with("Sat")), .id = "Group") 

    Group  Names     Sat1     Sat2 Program Pets Sat1_recode 
1  1  James    Satisfied  Very Dissatisfied  A Snake Satisfied 
2  1  Chris  Very Satisfied  Somewhat Satisfied  B Dog Satisfied 
3  1 Jessica   Dissatisfied    Neutral  A Dog Dissatisfied 
4  1 Tomoki Somewhat Satisfied    Neutral  C Dog Satisfied 
5  1  Anna   Dissatisfied    Satisfied  B Cat Dissatisfied 
6  1 Gerald    Neutral    Satisfied  D None  Neutral 
7  2  Tim Extremely Satisfied   Dissatisfied  A <NA> Satisfied 
8  2  John    Satisfied Somewhat Dissatisfied  B <NA> Satisfied 
... 
+0

Danke, das ist genau das, was ich gesucht habe! – Mike

+0

Liste (DF1, DF2)%>% Karte (~ mutate (., SatREC = Sat1%>% recode ('"Sehr zufrieden" = "Zufrieden"))) – Mike

+0

Schnelle Frage, mit Ihrer Antwort oben, habe ich auch gespielt herum mit der Auto-Recode-Funktion mit Karte und mutieren, die funktioniert. Der Code befindet sich im obigen Kommentar. Aber, wie würde ich den gleichen Code mit mutate_each schreiben und sowohl Sat1 als auch Sat2 einschließen? – Mike

1

ich große Recodierungen wie dies mit einem verbinden, in diesem Fall, dass ich auf einen langen Datenrahmen denke Umwandlung macht das Problem leichter zu denken.

library(tidyr) 
library(dplyr) 

mdf <- DF1 %>% 
    gather(var, value, starts_with("Sat")) 

recode_df <- data_frame(value = c("Extremely Satisfied","Satisfied","Somewhat Dissatisfied","Dissatisfied"), 
         recode = 1:4) 
mdf <- left_join(mdf, recode_df) 
mdf %>% spread(var, recode) 
+0

Danke für Ihre Antwort. Es gab mir einige Ideen, da ich nicht daran gedacht habe, diese Methode zu verwenden, um vorher zu rekodieren. Ich hoffe jedoch immer noch auf eine Antwort, die eine purrr Kartenfunktion verwendet. – Mike

+0

Ah, das Muster dort ist wahrscheinlich eine Funktion 'f' zu schreiben, die einen einzelnen Vektor rekodiert, dann benutze' df [] <- map_at (df, c ("SAT1", "SAT2"), f) ' – Shorpy

+0

Ja, das möchte ich machen. Ich denke jetzt muss ich die Funktion herausfinden. Ich hatte nicht viel Erfolg beim Erstellen einer Funktion, um die Faktoren wie in meinem obigen Beispiel zu reduzieren. Können Sie mir mit dem Code helfen? – Mike