这些问题与此我自己的话题相似 calculation of 90 percentile and replacement of it by median by groups in R
具有这种区别。
但是,在该主题中 请注意,计算是通过在一个操作类别之前的14个零完成的,但对于所有零操作类别并为每个组的code + item
执行中位数替换也就是说,现在我使用全零而不是14,并且不会碰到负数和零值。
通过针对Zero
类别的组变量(动作0、1),我希望通过返回变量找到75个百分位数,如果值大于75个百分位数,则必须在中间值上将其替换为zero
类别。因此,存在code
变量此过程必须对代码单独执行。注意:我不会触及负值和零值
mydat=structure(list(code = c(123L, 123L, 123L, 123L, 123L, 123L, 123L,
123L, 123L, 123L, 123L, 123L, 124L, 124L, 124L, 124L, 124L, 124L,
124L, 124L, 124L, 124L, 124L, 124L), action = c(0L, 0L, 0L, 0L,
0L, 0L, 1L, 1L, 1L, 1L, 1L, 1L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 1L,
1L, 1L, 1L, 1L), return = c(-1L, 0L, 23L, 100L, 18L, 15L, -1L,
0L, 23L, 100L, 18L, 15L, -1L, 0L, 23L, 100L, 18L, 15L, -1L, 0L,
23L, 100L, 18L, 15L)), .Names = c("code", "action", "return"), class = "data.frame", row.names = c(NA,
-24L))
\
23
100
18
15
如何获取输出。 75%:
42,25 中位数= 20,5个替换
add action return
123 0 -1
123 0 0
123 0 23
123 0 ***20,5
123 0 18
123 0 15
123 1 -1
123 1 0
123 1 23
123 1 100
123 1 18
123 1 15
124 0 -1
124 0 0
124 0 23
124 0 ***20,5
124 0 18
124 0 15
124 1 -1
124 1 0
124 1 23
124 1 100
124 1 18
124 1 15
使用最大的Uwe解决方案,我得到了错误
Error in `[.data.table`(mydat[action == 0, `:=`(output, as.double(return))], :
Column(s) [action] not found in i
library(data.table)
# mark the zero acton rows before the the action period
setDT(mydat)[, zero_before := cummax(action), by = .(code)]
# compute median and 90% quantile for that last 14 rows before each action period
agg <- mydat[zero_before == 0,
quantile(tail(return), c(0.5, 0.75)) %>%
as.list() %>%
set_names(c("med", "q90")) %>%
c(.(zero_before = 0)), by = .(code)]
agg
# append output column
mydat[action == 0, output := as.double(return)][
# replace output values greater q90 in an update non-equi join
agg, on = .(code,action, return > q90), output := as.double(med)][
# remove helper column
, zero_before := NULL]
答案 0 :(得分:1)
如果我理解正确,那么OP希望根据所有返回值大于0的零操作行来计算各组return
的中位数和75%的分位数。然后,零操作行中的任何返回值超过相应组75%的分位数的应替换为组中位数。
代码可以大大简化,因为我们不必在动作行之前和之后的零动作行之间进行区分。
下面的代码再现了预期的结果:
library(data.table)
library(magrittr)
# compute median and 90% quantile for that last 14 rows before each action period
agg <- setDT(mydat)[action == 0 & return > 0,
quantile(return, c(0.5, 0.75)) %>%
as.list() %>%
set_names(c("med", "q75")), by = .(code, action)]
# append output column
mydat[, output := as.double(return)][
# replace output values greater q75 in an update non-equi join
agg, on = .(code, action, return > q75), output := as.double(med)]
mydat[]
code action return output 1: 123 0 -1 -1.0 2: 123 0 0 0.0 3: 123 0 23 23.0 4: 123 0 100 20.5 5: 123 0 18 18.0 6: 123 0 15 15.0 7: 123 1 -1 -1.0 8: 123 1 0 0.0 9: 123 1 23 23.0 10: 123 1 100 100.0 11: 123 1 18 18.0 12: 123 1 15 15.0 13: 124 0 -1 -1.0 14: 124 0 0 0.0 15: 124 0 23 23.0 16: 124 0 100 20.5 17: 124 0 18 18.0 18: 124 0 15 15.0 19: 124 1 -1 -1.0 20: 124 1 0 0.0 21: 124 1 23 23.0 22: 124 1 100 100.0 23: 124 1 18 18.0 24: 124 1 15 15.0 code action return output