2016-05-23 15 views
0

Ich versuche, alle NAs mit einem anderen Wert zu füllen, der in derselben Spalte für Zeilen im selben Monat vorkommt. Gibt es dafür eine einfache Methode? Ich habe alle möglichen Funktionen gefunden, die fast, aber nicht ganz so funktionieren.Kopieren von Werten innerhalb der Spalte, basierend auf anderen Spaltenwerten

data.frame sieht wie folgt aus

id month price1 price2 
1 1   NA  2 
2 1   4  NA 
3 1   NA  NA 
1 2   6  NA 
2 2   NA  NA 
3 2   NA  4 

Ausgabe sollte wie folgt aussehen:

id month price1 price2 
1 1   4  2 
2 1   4  2 
3 1   4  2 
1 2   6  4 
2 2   6  4 
3 2   6  4 

Antwort

0

Diese Frage könnte besser in Stack sein, da sie auf die Programmierung in R fokussiert ist, aber hier ist ein Antwort:

Ich stelle mir vor, es gibt bessere Möglichkeiten, dies zu tun, aber die, die sofort in den Sinn kommt.

replace_nas <- function(df,var,id_var,func = function(x) x[!is.na(x)]) 
    return(merge(df[,-which(names(df)==var)],aggregate(as.formula(paste0(var,"~",id_var)),df,func))[,var]) 
replace_all_nas <- function(df,id_vars,select_var,agg_vars,func = function(x) x[!is.na(x)]) 
    return(cbind(df[,id_vars],sapply(agg_vars,function(x) replace_nas(df,x,select_var,func)))) 

Verbrauch: rufen replace_all_nas mit df als data.frame Sie diese Aktion ausführen wollen, id_vars ist ein Vektor der Namen der Spalten, die Sie festgelegt wollen, select_var ist die Variable, die Sie durch organisieren möchten, agg_vars sind die Variablen, die die NAs von ersetzen sollen, func ist die Funktion, die Sie verwenden möchten, um Nicht-Na-Werte zu sammeln, um die NAs zu ersetzen. Ich stelle dies ein, um die nicht-NA-Werte auszuwählen, unter der Annahme, dass es nur einen gibt, aber Sie würden etwas anderes benötigen, um damit umzugehen, wenn Sie mehrere nicht-NA-Werte in einer Spalte haben.

Laufen auf Ihrem Beispiel:

replace_all_nas(blah,id_vars = c("id","month"),select_var = c("month"),agg_vars = c("price1","price2"),func = function(x) x[!is.na(x)]) 
# id month price1 price2 
# 1 1  1  4  2 
# 2 2  1  4  2 
# 3 3  1  4  2 
# 4 1  2  6  4 
# 5 2  2  6  4 
# 6 3  2  6  4 
+0

Danke, ich werde auch mit diesem experimentieren! –

1

Ein möglicher Ansatz ist es, die match Funktion zu verwenden.

d <- data.frame(id = rep(1:3, 2), 
       month = rep(1:2, each=3), 
       price1 = c(NA, 4, NA, 6, NA, NA), 
       price2 = c(2, NA, NA, NA, NA, 4)) 

d[is.na(d$price1), "price1"] <- 
    d[!is.na(d$price1), ][match(d[is.na(d$price1), "month"], 
           d[!is.na(d$price1), "month"]), "price1"] 

d[is.na(d$price2), "price2"] <- 
    d[!is.na(d$price2), ][match(d[is.na(d$price2), "month"], 
           d[!is.na(d$price2), "month"]), "price2"] 

> d 
    id month price1 price2 
1 1  1  4  2 
2 2  1  4  2 
3 3  1  4  2 
4 1  2  6  4 
5 2  2  6  4 
6 3  2  6  4 

Beachten Sie, dass, wenn es mehr als eine nicht-fehlender Wert zu wählen ist, diese Methode den ersten nicht-fehlenden Wert verwenden.

Wie Laterow vorgeschlagen, können Sie Schleife über die Variablen:

for (j in 3:ncol(d)) { 
    varname <- names(d)[j] 
    d[is.na(d[, varname]), varname] <- 
    d[!is.na(d[, varname]), ][match(d[is.na(d[, varname]), "month"], 
            d[!is.na(d[, varname]), "month"]), 
           varname] 
} 
+0

Danke, hätten Sie einen Vorschlag, diese Methode zu iterieren? Ich habe vergessen zu erwähnen, ich habe etwa 400 Spalten. Kann ich einfach den Befehl mit "for i in ...." starten und dann price1/price2 durch i ersetzen? außerdem sind die mehreren Werte egal, es ist immer der gleiche Preis pro Produkt pro Monat :) –

+0

@larryfisherman Ersetzen Sie einfach 'd [is.na (d $ price1)," price1 "]' mit 'm <- Namen (d) [i]; d [is.na (d [, m]), m] ', und Schleife mit etwas wie' für (i in 3: ncol (d)) '. – Laterow

0

A dplyr Lösung. Es nimmt an, dass jeder "Monat" neben den NA einen einzelnen Wert hat.

Erstellen Sie einen Datenrahmen mit einer einzelnen Spalte für jeden Monat und neue Variablen mit dem einzelnen Wert in ihnen.

d1 <- d %>% group_by(month) 
%>% summarise(price1a = mean(price1,na.rm=TRUE),price2a=mean(price2,na.rm=TRUE)) 

Die neuen Spalten an den ursprünglichen Datenrahmen anhängen.

dplyr::left_join(d,d1,by="month") 
id month price1 price2 price1a price2a 
1 1  1  NA  2  4  2 
2 2  1  4  NA  4  2 
3 3  1  NA  NA  4  2 
4 1  2  6  NA  6  4 
5 2  2  NA  NA  6  4 
6 3  2  NA  4  6  4 
0

Ein Weg wäre ave. Funktionen können auf Gruppen gleicher Faktorstufen mit ave angewendet werden.

ave(df$price1, df$month, FUN=function(x)unique(x[!is.na(x)])) 

#[1] 4 4 4 6 6 6 

ave(df$price2, df$month, FUN=function(x)unique(x[!is.na(x)])) 
#[1] 2 2 2 4 4 4 
Verwandte Themen