用组值替换NA值

时间:2014-05-10 16:42:51

标签: r na

我有一个如下df,其中有5个家庭有20个人。家庭中的一些人缺少他们是否有医疗卡的数据。我想给这些人提供与其家庭中其他人相同的价值(不是NA值,实际的二进制值是0或1)。

我已经尝试了以下代码,这是我认为正确方向的一步 - 但不是100%正确,因为a)如果每个家庭的med_card的第一个值是NA并且b)它不起作用并不代替家庭1中所有人的NA。

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

任何指针都会非常感激, 谢谢

示例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

和代码

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)

期望的输出

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

5 个答案:

答案 0 :(得分:7)

试试ave。它将功能应用于组。有关详细信息,请查看?ave,例如:

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

请注意,只有当一个家庭中的所有值都不是NA并且不应该有所不同时(例如,人1 == 1,人2 == 0),这才有效。

答案 1 :(得分:6)

这正是动物园包中na.aggregatelink)的作用:

library(zoo)

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

这使用mean;但是,您可以指定您喜欢的任何功能。例如,如果您希望返回NA,如果组中的所有项都是NA(而不是NaN,如果给定零长度向量,则mean将返回),那么

meanNA <- function(x, ...) if (all(is.na(x))) NA else mean(x, ...)
transform(df, med_card_new = na.aggregate(med_card, by = hhold_no, FUN = meanNA))

答案 2 :(得分:4)

data.table解决方案

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

答案 3 :(得分:1)

还可以使用dplyr group_by(),然后利用带有max参数的na.rm之类的函数来返回每个组的所有数字。

library(dplyr)
df %>% group_by(hhold_no) %>% mutate(med_card_new = max(med_card, na.rm = T))

鉴于一组中的非缺失是数字和常数,您也可以使用meanmin代替max

答案 4 :(得分:0)

这很晚,但是如果要处理数字列,请尝试以下操作:

require(data.table)

setDT(df)[,'record_year':=mean( med_card,na.rm = T),by = c('hhold_no')]