【问题标题】:replace NA value with the group value用组值替换 NA 值
【发布时间】:2014-06-28 07:44:37
【问题描述】:

我有一个 df 如下,其中有 5 个家庭的 20 人。家庭中的一些人缺少关于他们是否拥有 med_card 的数据。我想给这些人与他们家中其他人相同的值(不是 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

【问题讨论】:

    标签: r na


    【解决方案1】:

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

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

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

    【讨论】:

      【解决方案2】:

      这有点晚了,但如果正在处理数字列,试试这个:

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

      【讨论】:

        【解决方案3】:

        这正是 zoo 包中的 na.aggregate (link) 所做的:

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

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

        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))
        

        【讨论】:

        • 谢谢,以前从未见过。非常便利。 :)
        • 刚刚很好地使用了这个,但是对于没有可以聚合的数据的案例得到了 NaN。将 NaN 正确转换为 NA 时遇到问题,发现最好的方法是 df[is.na(df)] &lt;- NA
        • mean 就是这样工作的。如果你取一个零长度向量的平均值,它会给出 NaN。如果您不希望这样,您可以指定备用功能。请参阅上面添加的代码。
        【解决方案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
        

        【讨论】:

          【解决方案5】:

          试试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)时才有效。

          【讨论】:

          • 谢谢!我用 ave 做了一些非常笨拙的尝试,但不能让它完全适合我。再次感谢! :)
          猜你喜欢
          • 2015-04-26
          • 1970-01-01
          • 1970-01-01
          • 2019-03-14
          • 2019-05-03
          • 1970-01-01
          • 2018-09-11
          • 2019-11-26
          相关资源
          最近更新 更多