2017-11-17 3 views
4

die minimale Beispiel vor:tidyverse mit Nachschlüssel zu verbreiten und NAs basierend auf eindeutige Schlüssel füllen

library(tidyverse) 
ex <-tribble(
    ~id, ~property, ~value, 
    1, "A",  9, 
    1, "A",  8, 
    1, "B",  7, 
    2, "A",  6, 
    2, "B",  5 
) 

Mein Ziel ist es, die Eigenschaft in Spalten zu verbreiten diese Tabelle zu erhalten:

tribble(
    ~id, ~A, ~B, 
    1, 9, 7, 
    1, 8, 7, 
    2, 6, 5 
) 

Gruppierung von id und property und Schlüsseladdiereinheit nahe kommt, aber lässt NA:

## almost but not quite 
ex %>% 
    group_by(id, property) %>% 
    mutate(key = row_number()) %>% 
    spread(property, value) %>% 
    select(-key) -> X 
X 

Gibt:

 id  A  B 
1  1  9  7 
2  1  8 NA 
3  2  6  5 

ich dies in der minimal Beispiel durch Aufspalten des oben von jedem property, fallen NAS- und Verbinden zurück durch id lösen kann:

inner_join(
    na.omit(select(X, id, A)), 
    na.omit(select(X, id, B)) 
) 

aber deutlich, dass verallgemeinern nicht zu beliebiger Satz von Eigenschaften. Was ist eine bessere tidyverse Strategie, dies zu tun?

HINWEIS: Mehrere vorherige Fragen sprechen mit der ersten Hälfte von diesem, z.B. Aufbau der key Spalte, so dass spread nicht fehlschlägt, konnte aber etwas nicht sehen, das die NA s adressiert.

+1

Sie nur 2 Werte für B, aber 3 für A, warum wollen Sie es nicht, um Ihnen ein 'NA' für B? Willst du die NA nur mit dem vorherigen Wert füllen? – useR

+0

@useR weil wir die Eigenschaft B für das Objekt mit der ID 1 kennen, basierend auf den anderen Zeilen für die ID 1. Im Wesentlichen ist die Eigenschaft A etwas, das mehrwertig sein kann (ThinkPaper mit der ID 1 kann mehrere 'keywords' haben) wo jeder in einer separaten Zeile erscheint, bc Ich mag keine Listenwerte in der Tabelle – cboettig

+0

Richtig, aber warum erwartest du das _program_ das zu wissen? Wenn du nur ein "B" in id1 aber zwei "A" hast "'s, der Schlüssel, der bei der Gruppierung durch' id 'und' property 'erzeugt wird, würde' 1 'und' 2 'für die zwei Werte von' A ', aber nur' 1 'für" B "haben. Dies erzeugt einen fehlenden Wert für B bei der Verbreitung, da es für "B" keine Taste == 2 gab. – useR

Antwort

5

Sie können fill von tidyr verwenden:

library(dplyr) 
library(tidyr) 

ex %>% 
    group_by(id, property) %>% 
    mutate(key = row_number()) %>% 
    spread(property, value) %>% 
    select(-key) %>% 
    group_by(id) %>% 
    fill(-id) 

Ergebnis:

# A tibble: 3 x 3 
# Groups: id [2] 
    id  A  B 
    <dbl> <dbl> <dbl> 
1  1  9  7 
2  1  8  7 
3  2  6  5 
+0

Füllung ist nett, aber es sieht so aus, als ob es nicht auf id, sondern nur auf der nächsten oder vorherigen Reihe basiert. Das scheint sehr zerbrechlich - sogar Sortierung nach ID zuerst, können wir nicht sicher sein, dass immer eine Zeile mit der gleichen ID sein wird. – cboettig

+1

@cboettig Sie können immer 'group_by (id)'. Siehe meine Bearbeitung. – useR

+1

Ich denke, es ist in diesem Fall tatsächlich bereits nach 'ID' gruppiert, gut zu wissen, dass die Füllung die Gruppe respektiert – cboettig

Verwandte Themen