计算R中的故障率和日期时间操作

Sha*_*ath 3 r reshape2 dplyr data.table

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

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)
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

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

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

Fail Rate = (Number of Fails)/(Number of Fails + Number of Pass)
Run Code Online (Sandbox Code Playgroud)

我想要的输出是这样的

                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
Run Code Online (Sandbox Code Playgroud)

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

Fra*_*ank 5

使用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)]
Run Code Online (Sandbox Code Playgroud)

这使

            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
Run Code Online (Sandbox Code Playgroud)

语法是DT[i,j,by]这里by是分组变量; 并j用于处理列.:=在内j创建新列.

重塑OP的期望输出......

dcast(res, d + antepost ~ Measurement, value.var = c("failrate", "N"))
Run Code Online (Sandbox Code Playgroud)

这使

            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
Run Code Online (Sandbox Code Playgroud)

感谢@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)
)
Run Code Online (Sandbox Code Playgroud)

这使

     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
Run Code Online (Sandbox Code Playgroud)

列名是从部件中的根变量~和每个函数定义的第一个字自动生成的.

  • 非常好,但如果数据集非常大,在分组操作之前创建`d`和`antepost`可能会更有效,因为`as.IDate`和`as.POSIXlt`不是很有效. (2认同)
  • @Sharath你可能没有最新版本的data.table包...?它正在我的努力.也许只是为了测试这段代码而开始一个新的R会话,并将`sessionInfo()`与CRAN上最新版本的data.table进行比较(目前为1.9.6) (2认同)
  • @Frank,完美.我刚刚更新了data.table包.这是一个很棒的解决方案.我只是将它应用到我更大的数据集中,它就像魅力一样.非常感谢弗兰克. (2认同)
  • 您也可以直接执行:`dcast(setDT(df1),as.IDate(Datetime)+ c("am","pm")[1+(小时(日期)> = 12)]〜测量,值.var ="PASSFAIL",fun.agg = list(function(x)sum(x!="PASS")/ length(x),length))` - `dcast.data.table`访问`fun中的多个函数.aggregate`也是. (2认同)