2015-02-13 5 views
5

sagen, dass ich die folgende Datenrahmen dfWie viele Datensätze in einer kollabieren, während NA Entfernen Werte

name <- c("Bill", "Rob", "Joe", "Joe") 
address <- c("123 Main St", "234 Broad St", NA, "456 North Ave") 
favteam <- c("Dodgers", "Mets", "Pirates", NA) 

df <- data.frame(name = name, 
       address = address, 
       favteam = favteam) 
df 

haben, die wie folgt aussieht:

name  address favteam 
1 Bill 123 Main St Dodgers 
2 Rob 234 Broad St Mets 
3 Joe   <NA> Pirates 
4 Joe 456 North Ave <NA> 

Was ich tun möchte, ist Kollaps nach Name (oder im Allgemeinen irgendeine Anzahl von ID-Variablen) und irgendeinen anderen Wert als NA den NA Wert in den endgültigen Daten ersetzen, so:

df_collapse <- foo(df) 

    name address  favteam 
1 Bill 123 Main St Dodgers 
2 Rob 234 Broad St  Mets 
3 Joe 456 North Ave Pirates 
+4

Kann Joe seine Meinung zu seinem Team ändern oder seine Adresse in der zweiten oder den folgenden Aufzeichnungen korrigieren? – vpipkt

+0

Joe lebt vom Netz und vermeidet aktiv Datensammler. Wir konnten ihn nur zweimal aufspüren und er war vehement dagegen, uns etwas über sein Leben zu erzählen, aber zum Glück liebt er es, Baseball zu reden ... – mcjudd

+0

Witze beiseite, verschiedene nicht-NA Antworten fügen meinem Problem eine weitere Falte hinzu, aber ich Ich dachte, ich würde es einen Schritt nach dem anderen machen. Gibt es Überlegungen, eine Hierarchie basierend auf der Reihenfolge der Ebenen in einer Faktorvariablen zu implementieren? Diese Art von Frage scheint auf SO nicht beantwortet worden zu sein ... – mcjudd

Antwort

10

Hier ist eine Option mit dplyr:

library(dplyr) 

df %>% 
    group_by(name) %>% 
    summarise_each(funs(first(.[!is.na(.)]))) # or summarise_each(funs(first(na.omit(.)))) 

#Source: local data frame [3 x 3] 
# 
# name  address favteam 
#1 Bill 123 Main St Dodgers 
#2 Joe 456 North Ave Pirates 
#3 Rob 234 Broad St Mets 

Und mit data.table:

library(data.table) 
setDT(df)[, lapply(.SD, function(x) x[!is.na(x)][1L]), by = name] 
# name  address favteam 
#1: Bill 123 Main St Dodgers 
#2: Rob 234 Broad St Mets 
#3: Joe 456 North Ave Pirates 

Oder

setDT(df)[, lapply(.SD, function(x) head(na.omit(x), 1L)), by = name] 

Edit:

Sie sagen, in Ihren tatsächlichen Daten haben Sie eine unterschiedliche Anzahl von Nicht-NA-Antworten pro Name. In diesem Fall kann der folgende Ansatz hilfreich sein.

Betrachten Sie diese modifizierte Beispieldaten (siehe letzte Zeile):

name <- c("Bill", "Rob", "Joe", "Joe", "Joe") 
address <- c("123 Main St", "234 Broad St", NA, "456 North Ave", "123 Boulevard") 
favteam <- c("Dodgers", "Mets", "Pirates", NA, NA) 

df <- data.frame(name = name, 
       address = address, 
       favteam = favteam) 

df 
# name  address favteam 
#1 Bill 123 Main St Dodgers 
#2 Rob 234 Broad St Mets 
#3 Joe   <NA> Pirates 
#4 Joe 456 North Ave <NA> 
#5 Joe 123 Boulevard <NA> 

Dann können Sie diesen data.table Ansatz verwenden, um die Nicht-NA-Antworten zu erhalten, die namentlich in der Zahl variiert werden kann:

setDT(df)[, lapply(.SD, function(x) unique(na.omit(x))), by = name] 
# name  address favteam 
#1: Bill 123 Main St Dodgers 
#2: Rob 234 Broad St Mets 
#3: Joe 456 North Ave Pirates 
#4: Joe 123 Boulevard Pirates 
+0

Große Antwort - Vielen Dank für Ihre Aufmerksamkeit auf das Detail, @docendo. Ich bin besonders von der "dplyr" -Lösung angezogen, da es auf meiner Liste steht, um mit der Syntax dieses Pakets vertrauter zu werden. Für diesen Teil: 'summarise_each (funs (first (. [! Is.na (.)]))))', Ist die Periode eine Abkürzung, um auf 'df' zu verweisen, gruppiert nach' name'? Ich wusste nicht, dass 'dplyr' nett mit Indizes gespielt hat. Ich wäre auch sehr dankbar, wenn Sie mich zu einem gründlichen Tutorial über die Feinheiten von 'dplyr' verweisen könnten. – mcjudd

+0

@mcjudd, froh, dass es funktioniert :) Das '.' in' summarise_each' bezieht sich auf die aktuellen Daten, die a) gruppiert und b) spaltenweise sind. Also '' first (. [! Is.na (.)]) 'Bedeutet: In jeder Spalte fassen wir zusammen und jede Gruppe von' name' in dieser Spalte nimmt den ersten Datenpunkt, der nicht 'NA' ist und gibt ihn als zusammengefasster Wert in dieser Spalte für diese Gruppe. Leider kann ich dir zu dplyr Tutorials nicht viel erzählen. Sie werden viele finden, wenn Sie es nur googeln, zum Beispiel [dieses von Hadley] (http://datascience.la/hadley-wickhams-dplyr-tutorial-at-user-2014-part-1/). –

+0

@mcjudd, Ich bin mir nicht sicher, ich verstehe genau, wie Sie es meinen, aber Sie könnten versuchen, die dplyr Pipe zu erweitern mit ...%>% mutate_each (Spaß (ersetzen (., Die (. == 0), 1 Sie können auch ifelse verwenden, aber replace ist schneller.Technisch können Sie das auch innerhalb der summarize tun, aber es würde es weniger lesbar machen und, was noch wichtiger ist, Sie müssen dies nicht gruppenweise machen (und nach der Zusammenfassung der Daten sind nicht mehr gruppiert, so dass es besser sein wird, wenn man danach mutiert). –

Verwandte Themen