【问题标题】:Calculation of failure rate and date time manipulation in RR中故障率和日期时间操作的计算
【发布时间】:2015-10-07 18:41:52
【问题描述】:

我有一个正在使用的示例数据框

Datetime <- c("2015-09-29 08:22:00", "2015-09-29 09:45:00", "2015-09-29 09:53:00", "2015-09-29 10:22:00", "2015-09-29 10:42:00",
                  "2015-09-29 11:31:00", "2015-09-29 11:47:00", "2015-09-29 12:45:00", "2015-09-29 13:11:00", "2015-09-29 13:44:00",
                  "2015-09-29 15:24:00", "2015-09-29 16:28:00", "2015-09-29 20:22:00", "2015-09-29 21:38:00", "2015-09-29 23:34:00")
Measurement <- c("Length","Length","Width","Height","Width","Height","Length","Width","Width","Height","Width","Length",
                     "Length","Height","Height")
PASSFAIL <- c("PASS","PASS","FAIL","PASS","PASS","FAIL_AVG_HIGH","FAIL#Pts","FAIL","FAIL_AVG_LOW","FAIL","PASS","PASS","FAIL#RNG#HIGH","PASS","FAIL")

df1 <- data.frame(Datetime,Measurement,PASSFAIL)

df1

              Datetime Measurement      PASSFAIL
1  2015-09-29 08:22:00      Length          PASS
2  2015-09-29 09:45:00      Length          PASS
3  2015-09-29 09:53:00       Width          FAIL
4  2015-09-29 10:22:00      Height          PASS
5  2015-09-29 10:42:00       Width          PASS
6  2015-09-29 11:31:00      Height FAIL_AVG_HIGH
7  2015-09-29 11:47:00      Length      FAIL#Pts
8  2015-09-29 12:45:00       Width          FAIL
9  2015-09-29 13:11:00       Width  FAIL_AVG_LOW
10 2015-09-29 13:44:00      Height          FAIL
11 2015-09-29 15:24:00       Width          PASS
12 2015-09-29 16:28:00      Length          PASS
13 2015-09-29 20:22:00      Length FAIL#RNG#HIGH
14 2015-09-29 21:38:00      Height          PASS
15 2015-09-29 23:34:00      Height          FAIL

我正在研究一个有趣的问题,以找出每天 12AM-12PM 和 12PM-12AM(第二天)每次测量的失败率。

注意:在 df1 中,PASSFAIL 列中有 FAIL 的任何内容都被视为失败。

Fail Rate = (Number of Fails)/(Number of Fails + Number of Pass)

我想要的输出是这样的

                Datetime FailRate_length Total_length FailRate_Width Total_Width FailRate_Height Total_Height
1 2015-09-29 00:00:00 AM            0.33            3           0.50           2            0.50            2
2 2015-09-29 12:00:00 PM            0.50            2           0.66           3            0.66            3

我正在尝试使用 dplyr 和 data.table 包来解决这个问题,但我只是不知道如何划分 df1 中的时间间隔以获得具有 2 个值的 df2 -> 12AM(df1 的前 7 个观察值)&中午 12 点(df1 中接下来的 8 个观测值)。有人可以帮我解决这个问题吗?

【问题讨论】:

    标签: r data.table dplyr reshape2


    【解决方案1】:

    使用 data.table...

    library(data.table)
    
    # thanks to @DavidArenburg for suggesting this approach:
    
    df1[, `:=`( 
      d        = as.IDate(Datetime), 
      antepost = c("am","pm")[1+(hour(Datetime) >= 12)] ) 
    ]
    
    res <- setDT(df1)[ , .( 
      failrate    = sum(PASSFAIL != "PASS")/.N,
      N           = .N
    ), by = .(d, antepost, Measurement)]
    

    这给了

                d antepost Measurement  failrate N
    1: 2015-09-29       am      Length 0.3333333 3
    2: 2015-09-29       am       Width 0.5000000 2
    3: 2015-09-29       am      Height 0.5000000 2
    4: 2015-09-29       pm       Width 0.6666667 3
    5: 2015-09-29       pm      Height 0.6666667 3
    6: 2015-09-29       pm      Length 0.5000000 2
    

    语法为DT[i,j,by],其中by 用于对变量进行分组; j 用于处理列。 :=j 内创建新列。

    要重塑为 OP 所需的输出...

    dcast(res, d + antepost ~ Measurement, value.var = c("failrate", "N"))
    

    给了

                d antepost failrate_Height failrate_Length failrate_Width N_Height N_Length N_Width
    1: 2015-09-29       am       0.5000000       0.3333333      0.5000000        2        3       2
    2: 2015-09-29       pm       0.6666667       0.5000000      0.6666667        3        2       3
    

    感谢@Arun,这是一种一步完成所有操作的方法:

    dcast(setDT(df1), 
      as.IDate(Datetime) + c("am","pm")[1+(hour(Datetime) >= 12)] ~ Measurement, 
      value.var = "PASSFAIL", 
      fun.agg = list(function(x) sum(x != "PASS")/length(x), length)
    )
    

    给了

         Datetime Datetime_1 PASSFAIL_function_Height PASSFAIL_function_Length PASSFAIL_function_Width PASSFAIL_length_Height PASSFAIL_length_Length PASSFAIL_length_Width
    1: 2015-09-29         am                0.5000000                0.3333333               0.5000000                      2                      3                     2
    2: 2015-09-29         pm                0.6666667                0.5000000               0.6666667                      3                      2                     3
    

    列名是从~ 部分中的根变量和每个函数定义的第一个单词自动生成的。

    【讨论】:

    • 非常好,虽然如果数据集非常大,在分组操作之前创建dantepost可能会更有效,因为as.IDateas.POSIXlt不是非常有效。
    • @Sharath 您可能没有最新版本的 data.table 包...?它正在为我工​​作。也许启动一个新的 R 会话只是为了测试这段代码,并将 sessionInfo() 与 CRAN 上最新版本的 data.table(当前为 1.9.6)进行比较
    • @Frank,完美。我刚刚更新了 data.table 包。这是一个很棒的解决方案。我只是将它应用于我更大的数据集,它就像魅力一样。非常感谢弗兰克。
    • @Sharath 好酷。希望你看看最后添加的部分。我同意 David 的观点,将分组变量添加到您的原始数据集中可能是有意义的。
    • 你也可以直接这样做:dcast(setDT(df1), as.IDate(Datetime) + c("am","pm")[1+(hour(Datetime) &gt;= 12)] ~ Measurement, value.var = "PASSFAIL", fun.agg=list(function(x) sum(x != "PASS")/length(x), length)) - dcast.data.table 也可以访问fun.aggregate 中的多个功能。
    【解决方案2】:

    dplyr + tidyr 等价物(分箱略有不同,尽管上面的很优雅):

    library(plyr)
    library(dplyr)
    library(tidyr)
    
    df1 %>%
      mutate(
        half_day = 
          Datetime %>%
          as.POSIXct(tz = "UTC") %>%
          round_any(60*60*12, f = floor) ) %>%
      group_by(half_day, Measurement) %>%
      summarize(Total = n(),
             FailRate = sum(PASSFAIL != "PASS")/Total) %>%
      gather(variable, value, FailRate, Total) %>%
      unite(variable_new, variable, Measurement, sep = "_") %>%
      spread(variable_new, value)
    

    gatherunitespread 序列是 dcast 的 tidyr 等价物。请注意

    半天*(12小时/半天)*(60分钟/小时)*(60秒/分钟)=60*60*12秒

    【讨论】:

      猜你喜欢
      • 2019-12-24
      • 1970-01-01
      • 1970-01-01
      • 2018-02-27
      • 2021-02-18
      • 2021-10-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多