我需要选择性地删除基于两个变量与数据集其余部分的成对比较的观察结果。
具体来说,这些都是成本效益数据,我想放弃主导'存在替代方案的干预措施 1.更昂贵 2.效果不佳
我的例子:
Township <- c(rep('A',3), rep('B',3))
Intervention <- rep(1:3, 2)
Cost <- c(1000, 500, 3000, 900, 1200, 1500)
Effect <- c(10, 8, 30, 10, 7, 8)
Res <- data_frame(Township, Intervention, Cost, Effect)
乡镇A是干预措施的正常情况,而且成本越来越高,越来越有效 乡镇B包含&#39;主导&#39;干预措施比替代措施更昂贵,效率更低,需要删除
以下内容无法扩展到更大的数据集,对我来说,反复崩溃RStudio ......!
Res.new <- Res %>%
group_by(Township) %>%
arrange(Cost) %>%
slice(-which(Effect<lag(Effect))[1],
-which(Effect<lag(Effect, k=2))[1]) # RStudio crashes
我需要的解决方案是按每个乡镇的成本排序的数据框 并且排除存在成本更高且效率更低的替代方案的任何示例
我正在寻找的结果:
Res.need <- Res %>% group_by(Township) %>% arrange(Cost)
Res.need <- Res.need[-c(5,6),]
在这种情况下,应排除第5行(B2),因为它比B1更昂贵且效率更低 同样,排除第6行(B3)的原因也是如此,但是基于滞后的解决方案可能会因为比前面的示例B2更有效而被卡住。
我认为使用过滤器可能有更好的方法。我已经搜索了解决方案,但只找到了基于与数据集进行比较的过滤器的示例,而不是与两个变量进行成对比较。
答案 0 :(得分:2)
有一种更好的方法可以使用 data.table 包,它既易于阅读(我的意思是代码),也比其他选择更快,更具可扩展性。
require(data.table)
Res.dt <- data.table(Res)
# figure out which intervention was least costly, within Township
Res.dt[, minCost := min(Cost), by = Township]
# get the Effect of the minimum cost intervention, within Township
Res.dt[, minCostEffect := Effect[Cost == minCost], by = Township][]
## Township Intervention Cost Effect minCost minCostEffect
## 1: A 1 1000 10 500 8
## 2: A 2 500 8 500 8
## 3: A 3 3000 30 500 8
## 4: B 1 900 10 900 10
## 5: B 2 1200 7 900 10
## 6: B 3 1500 8 900 10
# select out the dominated observations
Res.dt[!(Cost > minCost & Effect < minCostEffect)][]
## Township Intervention Cost Effect minCost minCostEffect
## 1: A 1 1000 10 500 8
## 2: A 2 500 8 500 8
## 3: A 3 3000 30 500 8
## 4: B 1 900 10 900 10
<强>增加:强>
这是一个矢量化解决方案,但正如您在评论中的新示例中所述,它并未捕获所有情况。问题是在乡镇内,我们需要将每种干预措施与所有其他干预措施进行比较。虽然通常我们应该避免R中的循环,但这似乎需要它。既然你没有在你的问题中提到速度,只是没有炸掉R,这应该还可以。
# data with new examples
Res <- data.frame(Township = c(rep('A',3), rep('B',3), rep('C',3)),
Intervention = rep(1:3, 3),
Cost = c(1000, 500, 3000, 900, 1200, 1500, 500, 600, 550),
Effect = c(10, 8, 30, 10, 7, 8, 5, 10, 11))
require(data.table)
Res.dt <- data.table(Res)
# function to find the dominated observations
findDominated <- function(data) {
data.split <- split(Res.dt, Res.dt[, Township])
dominated <- lapply(data.split, function(Res.subset) {
domSplit <- logical(nrow(Res.subset))
for (i in 1:nrow(Res.subset))
domSplit[i] <- any(Res.subset$Cost[i] > Res.subset$Cost & Res.subset$Effect[i] < Res.subset[["Effect"]])
domSplit
})
unlist(dominated, use.names = FALSE)
}
当应用于上述数据中定义的新案例时,我们现在具有您想要的选择行为,并且能够轻松选择这些主导案例并按照乡镇内的成本对结果进行排序:
Res.dt[, dominated := findDominated(Res.dt)][]
## Township Intervention Cost Effect dominated
## 1: A 1 1000 10 FALSE
## 3: A 3 3000 30 FALSE
## 2: A 2 500 8 FALSE
## 4: B 1 900 10 FALSE
## 5: B 2 1200 7 TRUE
## 6: B 3 1500 8 TRUE
## 7: C 1 500 5 FALSE
## 8: C 2 600 10 TRUE
## 9: C 3 550 11 FALSE
# sort by cost in each Township
setorder(Res.dt, Township, Cost)
# show non-dominated results
Res.dt[dominated == FALSE]
## Township Intervention Cost Effect dominated
## 1: A 2 500 8 FALSE
## 2: A 1 1000 10 FALSE
## 3: A 3 3000 30 FALSE
## 5: C 1 500 5 FALSE
## 4: B 1 900 10 FALSE
## 6: C 3 550 11 FALSE