【问题标题】:replace median for category by condition of three zero before and three after separated by groups in R用R中的组分隔的三个零之前和三个之后的条件替换类别的中位数
【发布时间】:2018-08-16 11:38:23
【问题描述】:

说,我有数据集

 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 code+item。这里有两组:

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

中位数=(2,4,3),(10,6,6)=5

所以在一个之前和之后一个零类别的中位数=5, 然后用这个中位数替换ones(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 的销售列的值也应该在输出列中。如何执行?

附:请不要注意此输出中的中位数大于销售额。这只是测试。

为埃里克

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

【问题讨论】:

    标签: r dplyr data.table plyr


    【解决方案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
    

    【讨论】:

    • Eric,任何问题,如何实现条件不是严格的三个零,而是从 1 到 3 个零。
    • @D.Joe,您能否发布一些包含所有边缘情况(例如只有 1 或 2 个零)和预期输出的示例数据?
    • 我编辑了帖子。在此示例中,我们在 1 个类别之前有两个零,在一个类别之后有 1 个零。有时会发生严格意义上的 3 个零,但最多有 3 个零。
    【解决方案2】:

    如果我理解正确,OP 希望将销售活动期间的销售数据与特定产品的销售活动前后的销售数据进行比较(codeitem)。

    预期输出是零操作日的销售数据。在行动日,该数字将替换为周围零行动日的中位数销售额,但前提是它低于实际销售额。

    每个销售操作的持续时间由active 列中的每条连续1s 给出。分别计算前后 3 个零行动日的中位数销售额。

    下面的函数

    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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-16
      • 1970-01-01
      • 1970-01-01
      • 2018-11-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多