2017-10-03 1 views
1
demodf <- data.frame(
    name = c("Mike","Mike","Mike","Mike","Mike","Joe","Joe","Joe","Joe","Joe"), 
    Field = c("EDUCATION","Degree","Title","WORK", "Title", "EDUCATION","Degree","Title", "WORK","Title"), 
    Values = c("EDUCATION", "Masters", "Student", "WORK", "VP Sales", "EDUCATION", "Bachelors","Student", "WORK", "Analyst")) 

    name  Field Values 
1 Mike EDUCATION EDUCATION 
2 Mike Degree Masters 
3 Mike  Title Student 
4 Mike  WORK  WORK 
5 Mike  Title VP Sales 
6 Joe EDUCATION EDUCATION 
7 Joe Degree Bachelors 
8 Joe  Title Student 
9 Joe  WORK  WORK 
10 Joe  Title Analyst 

Ich möchte tidyr::spread oder reshape2::dcast in Wide-Format, wo Field die Spaltenüberschriften wird.Tidy und Guss Daten mit Sockel in Reihen stecken

Dieser Code würde wie dcast(demodf, name ~ Values) oder demodf %>% spread(Field, Values) aussehen. dcast erzwingt jedoch eine numerische Eingabe und spread gibt einen Fehler aus.

Das Problem ist, dass "Titel" wiederholt wird. Sie können sehen, dass aufgrund einer Eigenart in den Daten, haben wir Bildung und Arbeit als "falsche" Header in den Daten. Ist es möglich, jeden Eintrag Field mit dem großgeschriebenen Header zu markieren, so dass dcast funktioniert (d. H. Title_EDUCATION und Title_WORK)? Und es wäre noch besser, diese Transformation auf das ganze Field anzuwenden, so dass "BILDUNG" und "ARBEIT" alle zusammen verschwinden, und wir bleiben bei Degree_EDUCATION, TITLE_EDUCATION ... usw.).

Hinweis, dass es viele weitere Header in den tatsächlichen Daten, so dass es am besten wäre, den „falschen Header“, wie die All-Cap-Einträge zu identifizieren, oder die Einträge, bei denen Field == Values

Ausgang Wunsch:

output <- data.frame(
Name=c("Mike", "Joe"), 
Degree_EDUCATION =c("Masters", "Bachelors"), 
Title_EDUCATION = c("Student", "Student"), 
Title_WORK= c("VP Sales", "Analyst")) 

    Name Degree_EDUCATION Title_EDUCATION Title_WORK 
1 Mike   Masters   Student VP Sales 
2 Joe  Bachelors   Student Analyst 

Antwort

3

Der Schlüssel ist, diese wiederholte Kategoriezeile als neue Spalte hinzuzufügen, dann können Sie leicht damit arbeiten.

Zuerst Zugabe stringsAsFactors=FALSE so vergleichen kann Field und Values:

demodf <- data.frame(
    name = c("Mike","Mike","Mike","Mike","Mike","Joe","Joe","Joe","Joe","Joe"), 
    Field = c("EDUCATION","Degree","Title","WORK", "Title", "EDUCATION","Degree","Title", "WORK","Title"), 
    Values = c("EDUCATION", "Masters", "Student", "WORK", "VP Sales", "EDUCATION", "Bachelors","Student", "WORK", "Analyst"), 
    stringsAsFactors=FALSE) 

Jetzt tidyr und dplyr verwenden, um Spalten für hinzufügen, wenn diese Zeile eine Kategorie ist und der Name dieser Kategorie, dann die fehlende zu füllen unten Werte, um dann die zusätzlichen Zeilen und Spalten zu entfernen.

library(tidyr) 
library(dplyr) 
d2 <- demodf %>% mutate(IsCategory=Field==Values, 
         Category=ifelse(IsCategory, Field, NA)) %>% 
    fill(Category) %>% subset(!IsCategory, select=-IsCategory) 
d2 
## name Field Values Category 
## 2 Mike Degree Masters EDUCATION 
## 3 Mike Title Student EDUCATION 
## 5 Mike Title VP Sales  WORK 
## 7 Joe Degree Bachelors EDUCATION 
## 8 Joe Title Student EDUCATION 
## 10 Joe Title Analyst  WORK 

dcast wird dann funktionieren, wie Sie hoffen!

library(reshape2)  
dcast(d2, name ~ Field+Category, value.var="Values") 
## name Degree_EDUCATION Title_EDUCATION Title_WORK 
## 1 Joe  Bachelors   Student Analyst 
## 2 Mike   Masters   Student VP Sales 
+0

Fantastisch, danke. Das 'mutate'-Bit zum Zuweisen des' IsCategory'-Tags ist ein großartiger Trick. – Mako212

0

Hier ist ein Versuch mit data.table. Dies erfordert, dass stringsAsFactors = FALSE verwendet wird.

library(data.table) 
# get groupings by titles (all caps) 
setDT(demodf)[, head := cumsum(Field == toupper(Field))] 
# merge titles onto full dataset and paste title to Field 
demodf[demodf[Field == toupper(Field), .(Field, head)], on="head", 
     Field := paste(Field, i.Field, sep="_"), by=.EACHI] 
# now reshape wide 
dcast(demodf[Values != toupper(Values),], name~Field, value.var="Values") 

Das gibt

name Degree_EDUCATION Title_EDUCATION Title_WORK 
1: Joe  Bachelors   Student Analyst 
2: Mike   Masters   Student VP Sales 

Daten

demodf <- 
structure(list(name = c("Mike", "Mike", "Mike", "Mike", "Mike", 
"Joe", "Joe", "Joe", "Joe", "Joe"), Field = c("EDUCATION", "Degree", 
"Title", "WORK", "Title", "EDUCATION", "Degree", "Title", "WORK", 
"Title"), Values = c("EDUCATION", "Masters", "Student", "WORK", 
"VP Sales", "EDUCATION", "Bachelors", "Student", "WORK", "Analyst" 
)), .Names = c("name", "Field", "Values"), row.names = c(NA, 
-10L), class = "data.frame")