说,我有数据集
mydat=structure(list(code = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L,
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L,
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L,
1L, 1L, 1L, 1L, 1L), .Label = "25481МСК", class = "factor"),
item = c(13163L, 13163L, 13163L, 13163L, 13163L, 13163L,
13163L, 13163L, 13163L, 13163L, 13163L, 13163L, 13163L, 13163L,
13163L, 13163L, 13163L, 13163L, 13163L, 13163L, 13163L, 13163L,
13164L, 13164L, 13164L, 13164L, 13164L, 13164L, 13164L, 13164L,
13164L, 13164L, 13164L, 13164L, 13164L, 13164L, 13164L, 13164L,
13164L, 13164L, 13164L, 13164L, 13164L, 13164L), sales = c(4L,
1L, 10L, 6L, 8L, 3L, 11L, 6L, 4L, 2L, 4L, 2L, 4L, 3L, 10L,
4L, 15L, 10L, 6L, 6L, 5L, 4L, 4L, 1L, 10L, 6L, 8L, 3L, 11L,
6L, 4L, 2L, 4L, 2L, 4L, 3L, 10L, 4L, 15L, 10L, 6L, 6L, 5L,
4L), action = c(0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L,
0L, 0L, 0L, 1L, 1L, 1L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L,
0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 1L, 1L, 0L, 0L,
0L, 0L, 0L)), .Names = c("code", "item", "sales", "action"
), class = "data.frame", row.names = c(NA, -44L))
我有2组vars代码和项目。这是两组:
25481МСК 13163
25480МСК 13164
我也有行动专栏。它只能有两个值零(0)或一(1)。 我需要按操作列按三个前面的零类别来计算中值,即按一列操作列来计算中位数,按操作列按三个零来计算该类别后的中位数。
这里是例子
sales action output
2 0 2
4 0 4
3 0 3
10 1 **5**
4 1 **5**
15 1 **5**
10 0 10
6 0 6
6 0 6
所以在1之前和之后= 5的中位数按零分类, 然后以该中位数代替行动中的人(1)。即这些零内的一个类别。因为从示例中可以看出,零内还有其他一个,因此必须对它们应用相同的原理。 但是,如果中位数大于销售额,则不要替换。
I.E。应该吧
sales action
10 1
5 1
14 1
并且零位中位数为12,因此在这种情况下输出将为
output
10
5
12
仅需替换14个,导致位数超过中位数。
在真实情况下
sales action output
2 0 2
4 0 4
3 0 3
10 1 **5**
4 1 **4**
15 1 **5**
10 0 10
6 0 6
6 0 6
25481МСК 13163
25480МСК 13164
所需的输出
code item sales action output
1 25481МСК 13163 4 0 4
2 25481МСК 13163 1 0 1
3 25481МСК 13163 10 0 10
4 25481МСК 13163 6 0 6
5 25481МСК 13163 8 0 8
6 25481МСК 13163 3 0 3
7 25481МСК 13163 11 0 11
8 25481МСК 13163 6 0 6
9 25481МСК 13163 4 0 4
10 25481МСК 13163 2 0 2
11 25481МСК 13163 4 0 4
12 25481МСК 13163 2 0 2
13 25481МСК 13163 4 0 4
14 25481МСК 13163 3 0 3
15 25481МСК 13163 10 1 5
16 25481МСК 13163 4 1 5
17 25481МСК 13163 15 1 5
18 25481МСК 13163 10 0 10
19 25481МСК 13163 6 0 6
20 25481МСК 13163 6 0 6
21 25481МСК 13163 5 0 5
22 25481МСК 13163 4 0 4
23 25481МСК 13164 4 0 4
24 25481МСК 13164 1 0 1
25 25481МСК 13164 10 0 10
26 25481МСК 13164 6 0 6
27 25481МСК 13164 8 0 8
28 25481МСК 13164 3 0 3
29 25481МСК 13164 11 0 11
30 25481МСК 13164 6 0 6
31 25481МСК 13164 4 0 4
32 25481МСК 13164 2 0 2
33 25481МСК 13164 4 0 4
34 25481МСК 13164 2 0 2
35 25481МСК 13164 4 0 4
36 25481МСК 13164 3 0 3
37 25481МСК 13164 10 1 5
38 25481МСК 13164 4 1 5
39 25481МСК 13164 15 1 5
40 25481МСК 13164 10 0 10
41 25481МСК 13164 6 0 6
42 25481МСК 13164 6 0 6
43 25481МСК 13164 5 0 5
44 25481МСК 13164 4 0 4
请注意,action = 0的sales列的值也应该在输出列中。如何执行?
P.S。请不要注意,该产出中位数多于销售额。这只是测试。
code item sales action output
52382МСК 11709 1 0 1
52382МСК 11709 10 1 NA
52382МСК 11709 1 0 1
52382МСК 11709 3 0 3
答案 0 :(得分:1)
我认为这接近解决方案? (说实话,我不确定我是否完全理解这个问题)
library(dplyr)
replacements <-
data_frame(
action1 = which(mydat$action == 1L),
group = rep(1:length(action1), each = 3, length.out = length(action1)),
sales1 = mydat$sales[action1],
sales_before = mydat$sales[action1 - 3L],
sales_after = mydat$sales[action1 + 3L]
) %>%
group_by(group) %>%
mutate(
med = median(c(sales_before, sales_after)),
output = pmin(sales1, med)
)
mydat$output <- mydat$sales
mydat$output[replacements$action1] <- replacements$output
mydat
答案 1 :(得分:1)
如果我理解正确,那么OP希望将销售行动期间的销售数字与特定产品(code
,item
)的销售行动前后的销售数字进行比较。
预期产出是零工作日的销售数字。在工作日,该数字将被周围的零工作日的平均销售额代替,但前提是该数字小于实际销售数字。
每个销售操作的持续时间由1
列中连续的active
的每个条纹给出。将分别计算前后三个零行动天的销售中位数。
具有以下功能
sales_action <- function(DF, zeros_before, zeros_after) {
library(data.table)
library(magrittr)
action_pattern <-
do.call(sprintf,
c(fmt = "%s1+(?=%s)",
stringr::str_dup("0", c(zeros_before, zeros_after)) %>% as.list()
))
message("Action pattern used: ", action_pattern)
setDT(DF)[, rn := .I]
tmp <- DF[, paste(action, collapse = "") %>%
stringr::str_locate_all(action_pattern) %>%
as.data.table() %>%
lapply(function(x) rn[x]),
by = .(code, item)][
, end := end + zeros_after]
DF[tmp, on = .(code, item, rn >= start, rn <= end),
med := as.double(median(sales[action == 0])), by = .EACHI][
, output := as.double(sales)][action == 1, output := pmin(sales, med)][
, c("rn", "med") := NULL][]
}
我们获得了示例数据集:
sales_action(mydat, 3L, 3L)
Action pattern used: 0001+(?=000) code item sales action output 1: 25481MCK 13163 4 0 4 2: 25481MCK 13163 1 0 1 3: 25481MCK 13163 10 0 10 4: 25481MCK 13163 6 0 6 5: 25481MCK 13163 8 0 8 6: 25481MCK 13163 3 0 3 7: 25481MCK 13163 11 0 11 8: 25481MCK 13163 6 0 6 9: 25481MCK 13163 4 0 4 10: 25481MCK 13163 2 0 2 11: 25481MCK 13163 4 0 4 12: 25481MCK 13163 2 0 2 13: 25481MCK 13163 4 0 4 14: 25481MCK 13163 3 0 3 15: 25481MCK 13163 10 1 5 16: 25481MCK 13163 4 1 4 17: 25481MCK 13163 15 1 5 18: 25481MCK 13163 10 0 10 19: 25481MCK 13163 6 0 6 20: 25481MCK 13163 6 0 6 21: 25481MCK 13163 5 0 5 22: 25481MCK 13163 4 0 4 23: 25481MCK 13164 4 0 4 24: 25481MCK 13164 1 0 1 25: 25481MCK 13164 10 0 10 26: 25481MCK 13164 6 0 6 27: 25481MCK 13164 8 0 8 28: 25481MCK 13164 3 0 3 29: 25481MCK 13164 11 0 11 30: 25481MCK 13164 6 0 6 31: 25481MCK 13164 4 0 4 32: 25481MCK 13164 2 0 2 33: 25481MCK 13164 4 0 4 34: 25481MCK 13164 2 0 2 35: 25481MCK 13164 4 0 4 36: 25481MCK 13164 3 0 3 37: 25481MCK 13164 10 1 5 38: 25481MCK 13164 4 1 4 39: 25481MCK 13164 15 1 5 40: 25481MCK 13164 10 0 10 41: 25481MCK 13164 6 0 6 42: 25481MCK 13164 6 0 6 43: 25481MCK 13164 5 0 5 44: 25481MCK 13164 4 0 4 code item sales action output
这符合OP的期望。
请注意,问题中显示的OP的期望输出是不完整的,因为OP并没有按照第16行和第38行的实际销售额替换中位数,因为它们应该按照OP自己的规则。
有关该功能的说明,请参见here。