2014-05-10 46 views
5

Tôi có df như sau, trong đó có 20 người trên 5 hộ gia đình. Một số người trong gia đình có dữ liệu bị thiếu cho dù họ có thẻ med_card hay không. Tôi muốn cung cấp cho những người này cùng một giá trị như những người khác trong gia đình của họ (không phải là giá trị NA, giá trị nhị phân thực là 0 hoặc 1).thay thế giá trị NA bằng giá trị nhóm

Tôi đã thử mã sau, đây là một bước đúng hướng tôi nghĩ - nhưng không đúng 100% vì a) nó không hoạt động nếu giá trị đầu tiên cho med_card cho mỗi hộ gia đình là NA và b) nó không thay thế NA cho tất cả mọi người trong gia đình 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)}) 

Bất kỳ con trỏ sẽ được đánh giá rất nhiều, Cảm ơn bạn

mẫu 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 

và mã để làm

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) 

đầu ra mong muốn

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 

Trả lời

6

Hãy thử ave. Nó áp dụng một chức năng cho các nhóm. Có một cái nhìn tại ?ave để biết chi tiết, ví dụ:

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 

Xin lưu ý rằng điều này sẽ chỉ làm việc nếu không phải tất cả các giá trị trong một hộ gia đình là NA và không nên phân biệt (ví dụ như người 1 == 1, người 2 == 0).

+0

cảm ơn bạn! Tôi đã thực hiện một số nỗ lực rất vụng về với ave, nhưng không thể làm cho nó hoạt động cho tôi. Cảm ơn một lần nữa! :) – user2363642

5

Đó là chính xác những gì na.aggregate (link) trong gói vườn thú không:

library(zoo) 

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

cảm ơn bạn, chưa bao giờ thấy điều này trước đây. rất tiện dụng. :) – user2363642

+0

Chỉ cần sử dụng tuyệt vời này, nhưng đã nhận NaN cho các trường hợp không có dữ liệu có thể tổng hợp. Đã gặp rắc rối khi chuyển đổi NaN sang NA đúng cách và phát hiện ra cách tốt nhất để làm như vậy là 'df [is.na (df)] <- NA'. – seeellayewhy

2

data.table giải pháp

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 
Các vấn đề liên quan