2016-06-09 17 views
8

Dies ist ein Beispiel meiner Daten aus CSV. Es enthält ~ 10 Spalten.Ersetzen von NA durch vorheriges Vorkommen

Product_id Product_Weight Product_Name Shop_Name ... 
[1] A    10    xxxx   Walmart 
[2] B    12    yyyy   Target 
[3] C    11    zzzz   Target 
[4] A    NA    xxxx   Walmart 
[5] C    NA    zzzz   Target 

Ich mag NA in Reihe 4 und 5 mit 10 bzw. 11 füllen (da dem Produktgewicht von A und C bereits aus der Reihe bekannt ist, 1 und 3). Ich mag der letzte Datenrahmen wie diese Was

Product_id Product_Weight Product_Name Shop_Name ... 
[1] A    10    xxxx   Walmart 
[2] B    12    yyyy   Target 
[3] C    11    zzzz   Target 
[4] A    10    xxxx   Walmart 
[5] C    11    zzzz   Target 

zu sein ist der beste Weg, dies in R zu tun?

+0

Sind diese Gewichte immer so festgelegt, dass eine Kombination aus Product_id - Product_name das gleiche Gewicht zurückgibt? – lmo

+0

@lmo Ja, das sind sie. – Avis

+0

Ein anderer Q & A über das Ersetzen von NA's: http://StackOverflow.com/Questions/32694313/Handle-Continous-Missing-Values-in-Time-Series-Data – Jaap

Antwort

5

Eine weitere Option mit dplyr und tidyr:

library(dplyr); library(tidyr); 
df %>% group_by(Product_id) %>% fill(Product_Weight) 

Source: local data frame [5 x 4] 
Groups: Product_id [3] 

    Product_id Product_Weight Product_Name Shop_Name 
     (fctr)   (int)  (fctr) (fctr) 
1   A    10   xxxx Walmart 
2   A    10   xxxx Walmart 
3   B    12   yyyy Target 
4   C    11   zzzz Target 
5   C    11   zzzz Target 

Das Ergebnis ist zwar nach Product_id sortiert.

+0

cant dplyr dies tun, ohne Nachbestellung? – rawr

9

Obwohl die Frage nach dem „vorherigen Auftreten“, fragte dies den Nachteil hätte, dass, wenn der erste Product_Weight in jedem Product_id wurden NA dann könnte es nicht auch auszufüllen, wenn wir die Product_Weight von einem nachfolgenden Product_id so wusste anstelle von das vorherige Vorkommen nehmen wir den Mittelwert aller Nicht-NAs mit dem gleichen Product_id. Da diese alle gleich sein sollten, ist ihr Mittelwert ihr gemeinsamer Wert.

Wenn Sie wirklich wollen, tun das vorherige Vorkommen verwenden, um die Prev Funktion Wo:

Prev <- function(x) na.locf(x, na.rm = FALSE) 

anstelle von na.aggregate in (1) und (3) und nicht verwenden (2).

Die folgenden Lösungen haben den Vorteil, dass sie alle:

  • die Reihenfolge der nicht

  • Arbeit, auch wenn der erste Product_Weight in jedem Product_id ist NA

    Eingang erhalten Ändern Sie den Eingang

Die erste Lösung hat den zusätzlichen Vorteil, dass sie nur eine Codezeile (plus eine library-Anweisung) enthält, und die zweite Lösung hat den zusätzlichen Vorteil, keine Pakete zu verwenden.

1) Zoo :: na.aggregate Wir verwenden na.aggregate im Zoo-Paket (die alle nationalen Agenturen mit dem Durchschnitt der nicht-nationalen Agenturen ersetzt), und wir wenden es auf Product_Weight separat für jeden Product_id.

library(zoo) 
transform(DF, Product_Weight = ave(Product_Weight, Product_id, FUN = na.aggregate)) 

geben:

Product_id Product_Weight Product_Name Shop_Name 
1   A    10   xxxx Walmart 
2   B    12   yyyy Target 
3   C    11   zzzz Target 
4   A    10   xxxx Walmart 
5   C    11   zzzz Target 

2) Keine Pakete Alternativ Mean anstelle von na.aggregate verwenden, wo Mean definiert ist als:

Mean <- function(x) replace(x, is.na(x), mean(x, na.rm = TRUE)) 

3) dplyr/Zoo hinzufügen Zeilennummern, gruppieren Sie nach der Product_id, füllen Sie die NAs wie in den früheren Lösungen unter Verwendung von entweder na.aggregate wie unten oder Mean, gezeigt in der ursprünglichen Reihenfolge arrangieren zurück und die Zeilennummern entfernen:

library(dplyr) 
library(zoo) 

DF %>% 
    mutate(row = row_number()) %>% 
    group_by(Product_id) %>% 
    mutate(Product_Weight = na.aggregate(Product_Weight)) %>% 
    ungroup() %>% 
    arrange(row) %>% 
    select(-row) 

Anmerkung: Dies wurde für die Eingabe verwendet DF:

Lines <- " Product_id Product_Weight Product_Name Shop_Name 
    A    10    xxxx   Walmart 
    B    12    yyyy   Target 
    C    11    zzzz   Target 
    A    NA    xxxx   Walmart 
    C    NA    zzzz   Target" 
DF <- read.table(text = Lines, header = TRUE) 
2

Hier Lösung mit Base R Befehle:

# create lookup table with item and weight combinations 
lookup<-unique(df[complete.cases(df[ ,1:2]),]) 

#  find the NAs needing replacement: which(is.na(df$weight)) 
#  find index in lookup tabe:match(df$a[which(is.na(df$weight)) 
#  subset: df$weight[which(is.na(df$weight)) 
df$weight[which(is.na(df$weight))]<-lookup$weight[match(df$Product_id[which(is.na(df$weight))], lookup$Product_id)] 

höchstwahrscheinlich nicht so effizient wie die dplyr/tidyr Lösung oben erwähnt.