首页 > 解决方案 > R dplyr:按组汇总数据时处理NA值和空/缺失行

问题描述

这是我的数据集:

library(dplyr)
library(lubridate)

d <- data.frame( individual=c(rep("A",1),rep("B",2),rep("C",5)),
                 date = as_date(c(rep("2020-02-01",1), rep("2020-03-02",2), rep("2020-04-01",5))),
                 test = c(NA, 0,1, 1,1,0,0,0),
                 date_test = c(NA,
                               as_date("2020-03-04"), as_date("2020-04-01"),
                               seq(as_date("2020-01-01"),as_date("2020-06-01"),length.out = 5)),
                 x= c(1.1, rep(2.1,2),rep(4,5)))
d <- d %>% as_tibble %>% mutate(date_test=as_date(as.numeric(date_test))) %>% group_by(individual) %>% mutate(before= date_test<date) %>%  ungroup()


# A tibble: 8 x 6
  individual date        test date_test      x before
  <fct>      <date>     <dbl> <date>     <dbl> <lgl> 
1 A          2020-02-01    NA NA           1.1 NA    
2 B          2020-03-02     0 2020-03-04   2.1 FALSE 
3 B          2020-03-02     1 2020-04-01   2.1 FALSE 
4 C          2020-04-01     1 2020-01-01   4   TRUE  
5 C          2020-04-01     1 2020-02-08   4   TRUE  
6 C          2020-04-01     0 2020-03-17   4   TRUE  
7 C          2020-04-01     0 2020-04-24   4   FALSE 
8 C          2020-04-01     0 2020-06-01   4   FALSE 

我想要的是创建一个新变量(我称之为“any_test”),它表示当按两个变量分组时是否有任何 test==1:“个人”和“之前”。因此,我想通过“个人”和“之前”级别将数据集减少为 1 行。另外,当变量any_test=1时,我想保留test=1的最后一个日期。最后我想保留“x”变量。

更清楚地说,这是我想使用 dpylr R 获得的预期结果:

  individual before test_any  date_test   x
1          A  FALSE        0       <NA> 1.1
2          A   TRUE        0       <NA> 1.1
3          B  FALSE        1 2020-04-01 2.2
4          B   TRUE        0       <NA> 2.2
5          C  FALSE        0       <NA> 4.0
6          C   TRUE        1 2020-02-08 4.0

标签: rdplyr

解决方案


如果我理解正确,这应该可以。我首先创建一个包含所有应该存在的组合的sceleton(在所有情况下为真/假之前,等等)。然后我将数据框减少到您感兴趣的值(如果有的话,最大测试日期),然后将其合并到数据框。

library(dplyr)
library(lubridate)
library(tidyverse)

d <- data.frame( individual=c(rep("A",1),rep("B",2),rep("C",5)),
                 date = as_date(c(rep("2020-02-01",1), rep("2020-03-02",2), rep("2020-04-01",5))),
                 test = c(NA, 0,1, 1,1,0,0,0),
                 date_test = c(NA,
                               as_date("2020-03-04"), as_date("2020-04-01"),
                               seq(as_date("2020-01-01"),as_date("2020-06-01"),length.out = 5)),
                 x= c(1.1, rep(2.1,2),rep(4,5)))
d <- d %>% as_tibble %>% mutate(date_test=as_date(as.numeric(date_test))) %>% group_by(individual) %>% mutate(before= date_test<date) %>%  ungroup()

sceleton <- distinct(d, individual, before, x) %>%
  complete(before, individual) %>%
  group_by(individual) %>%
  fill(x, .direction = "downup") %>%
  filter(!is.na(before))

only_tests <- d %>%
  filter(test==1) %>%
  rename(test_any = test) %>%
  select(individual, before, date_test,test_any) %>%
  group_by(individual, before) %>%
  slice_max(.,order_by = date_test,n = 1)

full <- sceleton %>%
  left_join(.,only_tests, by = c('before','individual')) %>%
  replace_na(., list(test_any = 0))

推荐阅读