2014-05-10 14 views
5

Ho un df come segue che ha 20 persone in 5 famiglie. Alcune persone all'interno della famiglia hanno dei dati mancanti se hanno o meno una med_card. Voglio dare a queste persone lo stesso valore delle altre persone nella loro famiglia (non un valore di NA, un vero valore binario che è 0 o 1).sostituire il valore NA con il valore di gruppo

Ho provato il seguente codice, che è un passo nella giusta direzione, penso - ma non è corretto al 100% perché a) non funziona se il primo valore per med_card per famiglia è NA e b) non sostituisce NA per tutte le persone nella casa 1.

DF<- ddply(df, .(hhold_no), function(df) {df$med_card[is.na(df$med_card)] <- head(df$med_card, na.rm=TRUE); return(df)}) 

Qualsiasi puntatori sarebbe molto apprezzato, Grazie

Esempio df

df 
    person_id hhold_no med_card 
1   1  1  1 
2   2  1  1 
3   3  1  NA 
4   4  1  NA 
5   5  1  NA 
6   6  2  0 
7   7  2  0 
8   8  2  0 
9   9  2  0 
10  10  3  NA 
11  11  3  NA 
12  12  3  NA 
13  13  3  1 
14  14  3  1 
15  15  4  1 
16  16  4  1 
17  17  5  1 
18  18  5  1 
19  19  5  NA 
20  20  5  NA 

e il codice per rendere

person_id<-as.numeric(c(1:20)) 
hhold_no<-as.numeric(c(1,1,1,1,1,2,2,2,2,3,3,3,3,3,4,4,5,5,5,5)) 
med_card<-as.numeric(c(1,1,NA,NA,NA,0,0,0,0,NA,NA,NA,1,1,1,1,1,1,NA,NA)) 
df<-data.frame(person_id,hhold_no, med_card) 

output desiderato

df 
    person_id hhold_no med_card med_card_new 
1   1  1  1   1 
2   2  1  1   1 
3   3  1  NA   1 
4   4  1  NA   1 
5   5  1  NA   1 
6   6  2  0   0 
7   7  2  0   0 
8   8  2  0   0 
9   9  2  0   0 
10  10  3  NA   1 
11  11  3  NA   1 
12  12  3  NA   1 
13  13  3  1   1 
14  14  3  1   1 
15  15  4  1   1 
16  16  4  1   1 
17  17  5  1   1 
18  18  5  1   1 
19  19  5  NA   1 
20  20  5  NA   1 

risposta

6

Prova ave. Applica una funzione ai gruppi. Date un'occhiata al ?ave per i dettagli, ad esempio:

df$med_card_new <- ave(df$med_card, df$hhold_no, FUN=function(x)unique(x[!is.na(x)])) 

# person_id hhold_no med_card med_card_new 
#1   1  1  1   1 
#2   2  1  1   1 
#3   3  1  NA   1 
#4   4  1  NA   1 
#5   5  1  NA   1 
#6   6  2  0   0 
#7   7  2  0   0 
#8   8  2  0   0 
#9   9  2  0   0 

prega di notare che questo sistema funziona solo se non tutti i valori di una famiglia sono NA e non dovrebbe essere diverso (ad esempio persona 1 == 1, 2 persona == 0).

+0

grazie! Avevo fatto alcuni tentativi maldestri con Ave, ma non riuscivo a farlo funzionare per me. Grazie ancora! :) – user2363642

5

Questo è esattamente ciò na.aggregate (link) nel pacchetto zoo fa:

library(zoo) 

transform(df, med_card_new = na.aggregate(med_card, by = hhold_no)) 
+0

grazie, non l'avevo mai visto prima. molto maneggevole. :) – user2363642

+0

Utilizzato semplicemente in modo meraviglioso, ma ha ottenuto i NaN per i casi che non avevano dati che potevano aggregare. Ho avuto problemi nel convertire correttamente NaN in NA e ho scoperto che il modo migliore per farlo è 'df [is.na (df)] <- NA'. – seeellayewhy

2

data.table soluzione

library(data.table) 
setDT(df)[, med_card2 := unique(med_card[!is.na(med_card)]), by = hhold_no] 

#  person_id hhold_no med_card med_card2 
# 1:   1  1  1   1 
# 2:   2  1  1   1 
# 3:   3  1  NA   1 
# 4:   4  1  NA   1 
# 5:   5  1  NA   1 
# 6:   6  2  0   0 
# 7:   7  2  0   0 
# 8:   8  2  0   0 
# 9:   9  2  0   0 
# 10:  10  3  NA   1 
# 11:  11  3  NA   1 
# 12:  12  3  NA   1 
# 13:  13  3  1   1 
# 14:  14  3  1   1 
# 15:  15  4  1   1 
# 16:  16  4  1   1 
# 17:  17  5  1   1 
# 18:  18  5  1   1 
# 19:  19  5  NA   1 
# 20:  20  5  NA   1 
Problemi correlati