我有一个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,请先删除已检查的行,然后再到达该行,然后继续检查下一组。
任何帮助将不胜感激!
答案 0 :(得分:0)
如果每个ID的MISC和MISC_2值一致,则可以
过滤所有具有na值的行,然后使用complete
和fill
填写丢失的数据。
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)