识别中断的观察

时间:2018-09-27 19:11:30

标签: r dplyr

我想找出一些缺失的现象,这些迹象表明清理/数据错误。

我的数据框多年来包含许多帐户。以下是遵循的规则:

  • 帐户可以创建或终止。在这些情况下,金额为$ 0或NA。这种观察(可能)不是不良数据的结果。
  • 帐户被NA或$ 0 打断的原因可能是数据错误或清理错误。

在下面的数据中,帐户A-E显示2001-2004年的金额。

df <- tribble(
       ~account,    ~"2001",     ~"2002",    ~"2003",  ~"2004",
       "Account.A",     100,          90,         87,       80,  #<Good   
       "Account.B",       0,          20,         30,       33,  #<Good
       "Account.C",      50,          55,          0,       0,   #<Good
       "Account.D",     200,         210,         NA,       210, #<Bad
       "Account.E",     150,           0,        212,       211) #<Bad

帐户A,B,C显示良好的数据:

  • 帐户A显示不间断数据
  • 帐户B显示的帐户始于2002年。
  • 帐户C显示的帐户于2003年到期,此后一直为$ 0。

帐户D和E显示错误数据:

  • 帐户D显示一个在2003年中断的帐户
  • 帐户E显示一个在2002年被中断的帐户

我的目标是识别中断的行(D,E)并标记它们。

我想要一个可以在很多年和数千个帐户中推广的解决方案。

1 个答案:

答案 0 :(得分:1)

这是一个tidyverse选项,它可能不是最漂亮的,但应该可以解决问题:

library(tidyverse)
df %>% 
  gather(year, value, `2001`:`2004`) %>% 
  group_by(account) %>% 
  mutate(order = if_else(year == min(year), 'first', 
                         if_else(year == max(year), 'last', 'mid'))) %>% 
  mutate(value = replace(value, is.na(value), 0)) %>% 
  mutate(start0 = row_number() >= min(row_number()[value != 0]),
         end0 = row_number() <= max(row_number()[value != 0])) %>% 
  mutate(check = if_else(order == 'mid' & value == 0 & start0 == TRUE & end0 == TRUE, TRUE, FALSE)) %>% 
  filter(check == TRUE)

# A tibble: 2 x 7
# Groups:   account [2]
  account   year  value order start0 end0  check
  <chr>     <chr> <dbl> <chr> <lgl>  <lgl> <lgl>
1 Account.E 2002      0 mid   TRUE   TRUE  TRUE 
2 Account.D 2003      0 mid   TRUE   TRUE  TRUE 

这里是一个解释:

  • 将数据从宽转换为长。
  • 按组确定帐户条目是其历史记录中的第一条,中间一条还是最后一条。
  • 由于零和NA的处理方式相同,因此将NA替换为零使操作起来更容易一些,但可以将其保持不变,并更新代码来处理它们。
  • TRUE / FALSE列用于确定从帐户历史记录的开头还是结尾开始是0值序列。
  • 如果一个帐户为0,而不是第一个或最后一个条目,并且不是从帐户历史记录的开头或结尾开始的0序列的一部分,则将该帐户标记为TRUE进行检查。
  • 最后,有一个过滤器仅过滤需要检查的帐户。