R-按组检测观察结束并删除多余的行

时间:2018-11-02 14:01:26

标签: r dplyr data.table

我有一个data.frame,它由大约30万行组成,每个ID有24行-每行代表每小时对该ID的观察。我的问题在于,对于某些ID,观察在24小时过去之前结束-但仍然有24行,其余的行在其3个观察变量中都具有NA。

在简化表中将是这样

ID    HOUR    OBS_1    OBS_2    OBS_3    MISC    MISC_2
1      0       29        32       34      19       21
1      1       21        12       NA      19       21
1      2       NA        24       NA      19       21
1      3       NA        NA       NA      19       21
1      4       NA        NA       NA      19       21
2      0       41        16       21      13       24
2      1       NA        NA       NA      13       24
2      2       11        30       41      13       24
2      3       21        NA       NA      13       24
2      4       24        35       21      13       24
2      5       NA        NA       NA      13       24
2      6       NA        NA       NA      13       24
3      0       NA        NA       NA      35       46
3      1       23        34       24      35       46
3      2       NA        26       NA      35       46
3      3       NA        NA       24      35       46
3      4       12        29       42      35       46
3      5       NA        NA       NA      35       46
3      6       NA        NA       NA      35       46

在表中,每个ID代表一个应适当处理的方案:

  • ID 1 :具有从0小时开始观察且在3小时结束观察的普通记录,因此该组的3和4小时行应删除

  • ID 2 :有一个小时(1),其中所有三个观察变量均设置为NA,但是观察得以恢复并在第5小时结束-因此应保留第2行( (由于注册错误而未结束观察),应删除第5和6小时的行。

  • ID 3 :从在所有三个观察变量中都具有NA的行开始,但是观察从下一个小时开始,直到第5小时结束。这类似于ID 2的情况。 ,但这一次发生在开始时(而不是在观察的中间)。但是,这仍然表示注册有误,应保留该组中从第5和6小时开始的行。

从概念上讲,我认为可能的解决方案是执行group_by ID,然后让R反向(从下至上)通过组中的行,直到遇到“ OBS_1”,“ OBS_2”所在的行和“ OBS_3”都不都是NA,请先删除已检查的行,然后再到达该行,然后继续检查下一组。

任何帮助将不胜感激!

2 个答案:

答案 0 :(得分:0)

如果每个ID的MISC和MISC_2值一致,则可以 过滤所有具有na值的行,然后使用completefill填写丢失的数据。

library(dplyr)
library(tidyr)
df %>% filter(!(is.na(OBS_1)&is.na(OBS_2)&is.na(OBS_3))) %>%
  group_by(ID) %>%
  complete(HOUR=0:max(HOUR)) %>%
  fill(MISC,MISC_2) %>% fill(MISC,MISC_2,.direction = "up")


# A tibble: 13 x 7
# Groups:   ID [3]
#       ID  HOUR OBS_1 OBS_2 OBS_3  MISC MISC_2
#    <int> <int> <int> <int> <int> <int>  <int>
#  1     1     0    29    32    34    19     21
#  2     1     1    21    12    NA    19     21
#  3     1     2    NA    24    NA    19     21
#  4     2     0    41    16    21    13     24
#  5     2     1    NA    NA    NA    13     24
#  6     2     2    11    30    41    13     24
#  7     2     3    21    NA    NA    13     24
#  8     2     4    24    35    21    13     24
#  9     3     0    NA    NA    NA    35     46
# 10     3     1    23    34    24    35     46
# 11     3     2    NA    26    NA    35     46
# 12     3     3    NA    NA    24    35     46
# 13     3     4    12    29    42    35     46

答案 1 :(得分:0)

如果在此之后不存在当天的观测值,则仅过滤缺失值,并保留所有不表示当天观测值结束的缺失观测值。这些还允许您的其他变量在一天中发生变化,因为如果达到观察值的结束,它只会删除它们。

 df %>% arrange(rev(as.numeric(rownames(.)))) %>% 
   group_by(ID) %>%
   mutate(rowNum = 1:n(),
          naObs = cumsum((is.na(OBS_1) & is.na(OBS_2) & is.na(OBS_3))), 
          missingBlock = naObs != rowNum) %>%
   slice(min(which(missingBlock)):n()) %>%
   ungroup() %>%
   arrange(rev(as.numeric(rownames(.)))) %>%
   select(-rowNum, -naObs, -missingBlock)