【问题标题】:Identify interrupted observations识别中断的观察
【发布时间】:2018-09-28 20:05:43
【问题描述】:

我想找出提示清理/数据错误的缺失观察结果。

我的数据框由多年来的许多帐户组成。以下是它遵循的规则:

  • 帐户可能被创建或终止。在这些情况下,金额为 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 显示的帐户始于 2​​002 年。
  • 帐户 C 显示的帐户于 2003 年到期,此后一直保持 0 美元。

账户 D 和 E 显示不良数据:

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

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

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

【问题讨论】:

    标签: r dplyr


    【解决方案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 以进行检查。
    • 最后,有一个过滤器可以只过滤需要检查的帐户。

    【讨论】:

    • 所有这些 mutate 调用都可以合并为一个,我只是碰巧发现如果每个步骤都有自己的调用更容易遵循。
    • 同意,不太确定真实数据是什么样的,所以使用arrange() 更安全。它确实适用于零开始/结束并且也被中断:df &lt;- tribble(~account, ~"2001", ~"2002", ~"2003", ~"2004", ~"2005", "Account.F", 0, 10, 0, 10, 10) 被标记为检查。还是我错过了什么?
    • 你能解释一下“不是零序列的一部分”部分吗?也就是说,布尔值start0end0
    • start0end0 从每个帐户的开头和结尾查找第一个非零值。 0,0,10,10 将标识第二个零是开始零序列的一部分,不应被视为中断,而 0,10,0,10 将被视为中断。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-29
    • 2019-08-19
    • 2023-03-25
    相关资源
    最近更新 更多