【问题标题】:Calculate the failure rate using a specific row limit in R使用 R 中的特定行限制计算故障率
【发布时间】:2015-11-02 01:09:57
【问题描述】:

我有一个这样的数据框

ID <- c("ID300","ID301","ID302","ID303","ID304","ID305","ID306","ID307","ID308","ID309")
Measurement <- c("Length","Length","Length","Length","Length","Length","Length","Length","Length","Length")
PASSFAIL <- c("FAIL","PASS","FAIL","FAIL#Pts","PASS","PASS","PASS","PASS","PASS","FAIL")

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

第 1 部分 我正在尝试为每个 ID 创建一个失败率列。我试图计算的方式是使用 5 个 ID 的窗口。例如

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

ID300 <- (Fails of Row1 to Row5)/(Total from Row1 to Row5) = (3/5) = 0.6

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

如果窗口大小小于 5,它也应该返回 NA,因此我想要的输出看起来像这样

      ID Measurement PASSFAIL  FR
1  ID300      Length     FAIL 0.6
2  ID301      Length     PASS 0.4
3  ID302      Length     FAIL 0.4
4  ID303      Length FAIL#Pts 0.2
5  ID304      Length     PASS 0.0
6  ID305      Length     PASS 0.2
7  ID306      Length     PASS  NA
8  ID307      Length     PASS  NA
9  ID308      Length     PASS  NA
10 ID309      Length     FAIL  NA

第 2 部分 完成此操作后,我需要考虑到相同的窗口 5,重新计算添加的每个新 ID 的失败率。例如,我想要的输出是

      ID Measurement PASSFAIL  FR
1  ID296      Length     PASS 0.4
2  ID297      Length     FAIL 0.6
3  ID298      Length     PASS 0.6
4  ID299      Length     FAIL 0.6
5  ID300      Length     FAIL 0.8
6  ID301      Length     FAIL 0.6
7  ID302      Length     PASS  NA
8  ID303      Length     FAIL  NA
9  ID304      Length FAIL#Pts  NA
10 ID305      Length     PASS  NA

我目前正在通过执行类似这样的操作来计算失败率,它会为整个数据帧计算失败率。考虑到窗口大小为 5,我不知道如何使用循环顺序计算每个 ID。

setDT(df1)
# aggregate
df1 <- df1[, .( FR = (sum(PASSFAIL != "PASS")/.N))]

请提供一些意见。

【问题讨论】:

  • 我建议您查看zoo 包中的filterrollapply。例如。 - filter(grepl("FAIL",df1$PASSFAIL), rep(1,5)/5, sides=1) 另请注意,您可以将 by= 参数传递给 data.table 以运行由 by= 变量定义的组内的函数。

标签: r dataframe data.table dplyr reshape2


【解决方案1】:

我迷失在你的第 2 部分,但这里是第 1 部分,使用stats::filtergrepl 调用来搜索包含"FAIL" 的所有值:

df1$FR <- NA
vals <- na.omit(filter(grepl("FAIL",df1$PASSFAIL), rep(1,5)/5, sides=1))
df1$FR[seq(1,length(vals))] <- vals

df1
#      ID Measurement PASSFAIL  FR
#1  ID300      Length     FAIL 0.6
#2  ID301      Length     PASS 0.4
#3  ID302      Length     FAIL 0.4
#4  ID303      Length FAIL#Pts 0.2
#5  ID304      Length     PASS 0.0
#6  ID305      Length     PASS 0.2
#7  ID306      Length     PASS  NA
#8  ID307      Length     PASS  NA
#9  ID308      Length     PASS  NA
#10 ID309      Length     FAIL  NA

或者:

rev(filter(grepl("FAIL",rev(df1$PASSFAIL)), rep(1,5)/5, sides=1))

如果你想变得花哨。

【讨论】:

  • thelatemail,感谢您提供此解决方案,但我收到错误消息“UseMethod("filter_") 中的错误:没有适用于 'filter_' 的方法应用于“逻辑”类的对象”我该怎么办摆脱它?是因为 dplyr 吗?
  • 我刚刚重新启动了 R 会话并在不使用 dplyr 的情况下再次运行它,它就像魅力一样。很棒的解决方案。非常感谢。但我稍后可能会在我的代码中使用 dplyr 吗?这会是个问题吗?
  • 我的第 2 部分不过是“移动失败率”。因为这实际上是一个时间序列数据,所以我希望这个解决方案能够计算每个添加到数据帧的新传入数据点。但我认为你的解决方案会做到这一点。问这个问题我可能真的很愚蠢,但我会测试它并让你知道。
  • @Sharath - 如果你加载了dplyr,你可以显式调用stats::filter() 而不是只调用filter
【解决方案2】:

您可能想尝试 sapply 函数,为了良好的顺序,我也将声明 df1 没有因素。

df1 <- data.frame(ID,Measurement,PASSFAIL,stringsAsFactors = FALSE)
df1$FR <- sapply(df1$ID,FUN = function(x) {
  if(which(df1$ID == x) > nrow(df1)-4){
    return(NA_real_)
  }else{
    start_ID <- which(df1$ID == x)
    end_ID <- start_ID + 4
    return(sum(grepl("FAIL",df1[start_ID:end_ID,"PASSFAIL"]))/5)
  }
})

【讨论】:

  • 这很好用,只是它忽略了“FAIl#”,并且只有在 passfail 列中的值是通过还是失败时才有效?您能否修改它以将“失败#”也视为失败?
  • 你怎么这么懒,伙计 :-),把我的 == 换成 grepl
猜你喜欢
  • 1970-01-01
  • 2018-06-14
  • 2019-12-24
  • 2021-02-25
  • 2011-03-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多