以14天和7天为间隔,计算R组的90%并用中位数替换
这篇文章与我的文章相关 jyjek的解决方案帮助了我,但并没有完全帮助我以14天和7天为间隔,计算R组的90%并用中位数替换,r,dplyr,data.table,R,Dplyr,Data.table,这篇文章与我的文章相关 jyjek的解决方案帮助了我,但并没有完全帮助我 mydat%>% group_by(code,item)%>% mutate(output=ifelse(return>quantile(return,.9) & action==0,median(return),return)) 有计算中位数和90%的条件 在OP中,我写道 注:在一个行动类别之前,计算由14个零完成,但在所有零行动类别和每个组别代码+项目中,由中间值替换。如何计算
mydat%>%
group_by(code,item)%>%
mutate(output=ifelse(return>quantile(return,.9) & action==0,median(return),return))
有计算中位数和90%的条件
在OP中,我写道
注:在一个行动类别之前,计算由14个零完成,但在所有零行动类别和每个组别代码+项目中,由中间值替换。如何计算一类行动前14个零+一类行动后7个零的90%分位数,但必须用中位数替换所有零类行动,并对每组代码+项目执行
这里是部分数据
mydat=structure(list(code = c(123L, 123L, 123L, 123L, 123L, 123L, 123L,
123L, 123L, 123L, 123L, 123L, 123L, 123L, 123L, 123L, 123L, 123L,
123L, 123L, 123L, 123L, 123L, 123L, 123L, 123L, 123L, 123L, 123L,
123L, 123L, 123L, 123L, 123L, 123L, 123L, 123L, 123L, 123L, 123L,
123L, 123L, 123L, 123L, 123L, 123L, 123L, 222L, 222L, 222L, 222L,
222L, 222L, 222L, 222L, 222L, 222L, 222L, 222L, 222L, 222L, 222L,
222L, 222L, 222L, 222L, 222L, 222L, 222L, 222L, 222L, 222L, 222L,
222L, 222L, 222L, 222L, 222L, 222L, 222L, 222L, 222L, 222L, 222L,
222L, 222L, 222L, 222L, 222L, 222L, 222L, 222L, 222L, 222L),
item = c(234L, 234L, 234L, 234L, 234L, 234L, 234L, 234L,
234L, 234L, 234L, 234L, 234L, 234L, 234L, 234L, 234L, 234L,
234L, 234L, 234L, 234L, 234L, 234L, 234L, 234L, 234L, 234L,
234L, 234L, 234L, 234L, 234L, 234L, 234L, 234L, 234L, 234L,
234L, 234L, 234L, 234L, 234L, 234L, 234L, 234L, 234L, 333L,
333L, 333L, 333L, 333L, 333L, 333L, 333L, 333L, 333L, 333L,
333L, 333L, 333L, 333L, 333L, 333L, 333L, 333L, 333L, 333L,
333L, 333L, 333L, 333L, 333L, 333L, 333L, 333L, 333L, 333L,
333L, 333L, 333L, 333L, 333L, 333L, 333L, 333L, 333L, 333L,
333L, 333L, 333L, 333L, 333L, 333L), return = c(25L, 25L,
21L, 37L, 23L, 27L, 19L, 7L, 16L, 12L, 33L, 24L, 6L, 14L,
4L, 25L, 90L, 27L, 3L, 16L, 7L, 1L, 13L, 11L, 36L, 5L, 6L,
14L, 11L, 41L, 11L, 6L, 4L, 11L, 3L, 6L, 21L, 41L, 28L, 30L,
92L, 4L, 1L, 83L, 3L, 16L, 4L, 25L, 25L, 21L, 37L, 23L, 27L,
19L, 7L, 16L, 12L, 33L, 24L, 6L, 14L, 4L, 25L, 90L, 27L,
3L, 16L, 7L, 1L, 13L, 11L, 36L, 5L, 6L, 14L, 11L, 41L, 11L,
6L, 4L, 11L, 3L, 6L, 21L, 41L, 28L, 30L, 92L, 4L, 1L, 83L,
3L, 16L, 4L), action = c(0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L,
0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L,
0L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 1L, 1L, 1L, 0L, 0L, 0L, 0L,
0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L,
0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L,
0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 1L, 1L, 1L, 0L, 0L,
0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L)), .Names = c("code",
"item", "return", "action"), class = "data.frame", row.names = c(NA,
-94L))
我有2个组变量代码+项。这里有两组:
123 234
222 333
我还有行动专栏。它只能有两个值(类别)零(0)或一(1)
我需要通过返回列的零动作类别来计算90个百分点
,它位于一个动作类别之前。
然后我需要通过返回列的零动作类别来计算中位数,它位于一个动作类别之前
如何计算一类行动前14个零+1类行动后7个零的90%分位数,
然后我必须找到上面计算的90%以上的值,然后这些值必须由计算的中位数来代替。
但必须为所有零行动类别和每个组别代码+项目执行中位数替换
在一个动作类别之后,返回列再次归零。为此,我也必须找到上面计算的90%以上的值,然后用上面计算的中位数来代替这个值
注意,计算
在一类动作前加14个零,在一类动作后加7个零。
但是,对于所有零类
动作,都要用中位数替换
并为每组执行code+项目
结果可以在输出列中
更清楚地说,这里需要输出
对于123+234
组
百分之九十=41
中位数=14
code item return action output
1 123 234 25 0 25
2 123 234 25 0 25
3 123 234 21 0 21
4 123 234 37 0 16
5 123 234 23 0 23
6 123 234 27 0 27
7 123 234 19 0 19
8 123 234 7 0 7
9 123 234 16 0 16
10 123 234 12 0 12
11 123 234 33 0 33
12 123 234 24 0 24
13 123 234 6 0 6
14 123 234 14 0 14
15 123 234 4 0 4
16 123 234 25 0 25
17 123 234 90 0 **14**
18 123 234 27 0 27
19 123 234 3 0 3
20 123 234 16 0 16
21 123 234 7 0 7
22 123 234 1 0 1
23 123 234 13 0 13
24 123 234 11 0 11
25 123 234 36 0 36
26 123 234 5 0 5
27 123 234 6 0 6
28 123 234 14 0 14
29 123 234 11 0 11
30 123 234 41 0 **14**
31 123 234 11 1 Na
32 123 234 6 1 Na
33 123 234 4 1 Na
34 123 234 11 1 Na
35 123 234 3 0 3
36 123 234 6 0 6
37 123 234 21 0 21
38 123 234 41 0 **14**
39 123 234 28 0 28
40 123 234 30 0 30
41 123 234 92 0 **14**
42 123 234 4 0 4
43 123 234 1 0 1
44 123 234 83 0 **14**
45 123 234 3 0 3
46 123 234 16 0 16
47 123 234 4 0 4
48 222 333 25 0 25
49 222 333 25 0 25
50 222 333 21 0 21
51 222 333 37 0 16
52 222 333 23 0 23
53 222 333 27 0 27
54 222 333 19 0 19
55 222 333 7 0 7
56 222 333 16 0 16
57 222 333 12 0 12
58 222 333 33 0 33
59 222 333 24 0 24
60 222 333 6 0 6
61 222 333 14 0 14
62 222 333 4 0 4
63 222 333 25 0 25
64 222 333 90 0 **14**
65 222 333 27 0 27
66 222 333 3 0 3
67 222 333 16 0 16
68 222 333 7 0 7
69 222 333 1 0 1
70 222 333 13 0 13
71 222 333 11 0 11
72 222 333 36 0 36
73 222 333 5 0 5
74 222 333 6 0 6
75 222 333 14 0 14
76 222 333 11 0 11
77 222 333 41 0 **14**
78 222 333 11 1 Na
79 222 333 6 1 Na
80 222 333 4 1 Na
81 222 333 11 1 Na
82 222 333 3 0 3
83 222 333 6 0 6
84 222 333 21 0 21
85 222 333 41 0 **14**
86 222 333 28 0 28
87 222 333 30 0 30
88 222 333 92 0 **14**
89 222 333 4 0 4
90 222 333 1 0 1
91 222 333 83 0 **14**
92 222 333 3 0 3
93 222 333 16 0 16
94 222 333 4 0 4
对于222+333
百分之九十=41
中位数=14
code item return action output
1 123 234 25 0 25
2 123 234 25 0 25
3 123 234 21 0 21
4 123 234 37 0 16
5 123 234 23 0 23
6 123 234 27 0 27
7 123 234 19 0 19
8 123 234 7 0 7
9 123 234 16 0 16
10 123 234 12 0 12
11 123 234 33 0 33
12 123 234 24 0 24
13 123 234 6 0 6
14 123 234 14 0 14
15 123 234 4 0 4
16 123 234 25 0 25
17 123 234 90 0 **14**
18 123 234 27 0 27
19 123 234 3 0 3
20 123 234 16 0 16
21 123 234 7 0 7
22 123 234 1 0 1
23 123 234 13 0 13
24 123 234 11 0 11
25 123 234 36 0 36
26 123 234 5 0 5
27 123 234 6 0 6
28 123 234 14 0 14
29 123 234 11 0 11
30 123 234 41 0 **14**
31 123 234 11 1 Na
32 123 234 6 1 Na
33 123 234 4 1 Na
34 123 234 11 1 Na
35 123 234 3 0 3
36 123 234 6 0 6
37 123 234 21 0 21
38 123 234 41 0 **14**
39 123 234 28 0 28
40 123 234 30 0 30
41 123 234 92 0 **14**
42 123 234 4 0 4
43 123 234 1 0 1
44 123 234 83 0 **14**
45 123 234 3 0 3
46 123 234 16 0 16
47 123 234 4 0 4
48 222 333 25 0 25
49 222 333 25 0 25
50 222 333 21 0 21
51 222 333 37 0 16
52 222 333 23 0 23
53 222 333 27 0 27
54 222 333 19 0 19
55 222 333 7 0 7
56 222 333 16 0 16
57 222 333 12 0 12
58 222 333 33 0 33
59 222 333 24 0 24
60 222 333 6 0 6
61 222 333 14 0 14
62 222 333 4 0 4
63 222 333 25 0 25
64 222 333 90 0 **14**
65 222 333 27 0 27
66 222 333 3 0 3
67 222 333 16 0 16
68 222 333 7 0 7
69 222 333 1 0 1
70 222 333 13 0 13
71 222 333 11 0 11
72 222 333 36 0 36
73 222 333 5 0 5
74 222 333 6 0 6
75 222 333 14 0 14
76 222 333 11 0 11
77 222 333 41 0 **14**
78 222 333 11 1 Na
79 222 333 6 1 Na
80 222 333 4 1 Na
81 222 333 11 1 Na
82 222 333 3 0 3
83 222 333 6 0 6
84 222 333 21 0 21
85 222 333 41 0 **14**
86 222 333 28 0 28
87 222 333 30 0 30
88 222 333 92 0 **14**
89 222 333 4 0 4
90 222 333 1 0 1
91 222 333 83 0 **14**
92 222 333 3 0 3
93 222 333 16 0 16
94 222 333 4 0 4
**我标记了值被中位数替换的行
计算百分位和中位数的数据
return action
90 0
27 0
3 0
16 0
7 0
1 0
13 0
11 0
36 0
5 0
6 0
14 0
11 0
41 0
11 1
6 1
4 1
11 1
3 0
6 0
21 0
41 0
28 0
30 0
92 0
一类动作前14个零+一类动作后7个零
重要编辑
我怀疑这个错误的原因
这里是数据
item return code action
1 11202 6 137 0
2 11202 3 137 0
3 11202 5 137 0
4 11202 6 137 0
5 11202 4 137 0
6 11202 10 137 0
7 11202 1 137 0
8 11202 19 137 0
9 11202 16 137 0
10 11202 6 137 0
11 11202 11 137 0
12 11202 20 137 0
13 11202 19 137 0
14 11202 13 137 0
15 11202 14 137 0
16 11202 13 137 0
17 11202 21 137 0
18 11202 10 137 0
19 11202 16 137 0
20 11202 8 137 0
21 11202 15 137 0
22 11202 8 137 0
23 11202 25 137 0
24 11202 17 137 0
25 11202 21 137 0
26 11202 14 137 0
27 11202 15 137 0
28 11202 6 137 0
29 11202 5 137 0
30 11202 11 137 0
31 11202 11 137 0
32 11202 8 137 0
33 11202 12 137 1
38 11202 17 137 1
39 11202 9 137 0
40 11202 7 137 0
41 11202 4 137 0
正如你所看到的,在一类动作之前,我们有14个零,但在一类动作之后,我们只有4个零
在这种情况下,我们先计算14个零,然后再计算4个零。
可能是这种情况
编辑三
中位数和百分位数由这些数据计算,前10个,后7个
70
71
37
20
49
102
113
110
117
42
43
33
53
101
61
13
51
中位数是53,但所有超过90%的数据都被替换为68,因为68是所有OB的中位数。我对你的问题的理解是:
- 根据
code
和item
您有一系列行action==1
- 您希望在该范围前取10行,在该范围后取7行
- 对于这17行,其中
action==0
保持不变,得到90%的分位数
- 然后将
action==0的所有行与该分位数进行比较。如果该值大于或等于,则将其替换为与操作
无关的所有行的平均值
如果这是正确的,则可以使用以下方法:
library(dplyr)
get_mask <- function(action) {
ones <- which(action == 1)
end_before <- max(0, min(ones) - 1)
start_before <- max(0, end_before - 9)
start_after <- min(length(action), max(ones) + 1)
end_after <- min(length(action), start_after + 6)
indices <- c(seq.int(from = start_before, to = end_before),
seq.int(from = start_after, to = end_after))
result <- rep(NA_real_, length(action))
result[indices] <- 1
result
}
mydat %>%
group_by(code,item) %>%
mutate(mask = get_mask(action)) %>%
mutate(output = ifelse(return>=quantile(mask * return, .9, na.rm = TRUE) & action==0,
median(return), return))
库(dplyr)
了解我对你问题的理解:
- 根据
code
和item
您有一系列行action==1
- 您希望在该范围前取10行,在该范围后取7行
- 对于这17行,其中
action==0
保持不变,得到90%的分位数
- 然后将
action==0的所有行与该分位数进行比较。如果该值大于或等于,则将其替换为与操作
无关的所有行的平均值
如果这是正确的,则可以使用以下方法:
library(dplyr)
get_mask <- function(action) {
ones <- which(action == 1)
end_before <- max(0, min(ones) - 1)
start_before <- max(0, end_before - 9)
start_after <- min(length(action), max(ones) + 1)
end_after <- min(length(action), start_after + 6)
indices <- c(seq.int(from = start_before, to = end_before),
seq.int(from = start_after, to = end_after))
result <- rep(NA_real_, length(action))
result[indices] <- 1
result
}
mydat %>%
group_by(code,item) %>%
mutate(mask = get_mask(action)) %>%
mutate(output = ifelse(return>=quantile(mask * return, .9, na.rm = TRUE) & action==0,
median(return), return))
库(dplyr)
获取_mask如果我理解正确,则每个code
,项目
组的操作
列由一系列的零组成,后面是一个连续的一个,最后是另一系列的零。每组中只有一个连续的一个
OP想要
计算最后14个“零动作行”(即动作==0
的行)在动作==1
的第一行之前的90%分位数和中位数,以及在动作==1
的最后一行之后的前7行,分别针对每个代码
,项目
组
从OP的编辑:如果action
中的连串1之前少于14个零或之后少于7个零,则将计算可用零操作行的统计信息
将操作==0的所有行的返回值
复制到输出
如果输出值大于或等于90%分位数,则将其替换为每组第一个操作==1行之前所有零操作行的中值。
请注意,OP讨论的是找到90%以上的值,这意味着更大的关系,但预期结果也替换了返回值等于90%分位数的值
这可以通过在非等连接中进行更新并进行一些准备来解决。关键部分是识别一条线之前的零动作行和一条线之后的零动作行。对于第一个action==1
行之前的零操作行,这是通过cummax(action)
实现的;对于第一个action==1之后的零操作行,这是通过双反转rev(cummax(rev(action))
实现的
agg
code item med q90 action
1: 123 234 14 41 0
2: 222 333 14 41 0
mydat[action == 0, output := as.double(return)][
# replace output values greater q90 in an update non-equi join
agg, on = .(code, item, action, return > q90), output := as.double(med)][
# remove helper column
, c("zero_before", "zero_after") := NULL]
code item return action output
1: 123 234 90 0 14
2: 123 234 41 0 14
3: 123 234 41 0 14
4: 123 234 92 0 14
5: 123 234 83 0 14
6: 222 333 90 0 14
7: 222 333 41 0 14
8: 222 333 41 0 14
9: 222 333 92 0 14
10: 222 333 83 0 14
mydat <-
structure(list(item = c(11202L, 11202L, 11202L, 11202L, 11202L,
11202L, 11202L, 11202L, 11202L, 11202L, 11202L, 11202L, 11202L,
11202L, 11202L, 11202L, 11202L, 11202L, 11202L, 11202L, 11202L,
11202L, 11202L, 11202L, 11202L, 11202L, 11202L, 11202L, 11202L,
11202L, 11202L, 11202L, 11202L, 11202L, 11202L, 11202L, 11202L
), return = c(6L, 3L, 5L, 6L, 4L, 10L, 1L, 19L, 16L, 6L, 11L,
20L, 19L, 13L, 14L, 13L, 21L, 10L, 16L, 8L, 15L, 8L, 25L, 17L,
21L, 14L, 15L, 6L, 5L, 11L, 11L, 8L, 12L, 17L, 9L, 7L, 4L), code = c(137L,
137L, 137L, 137L, 137L, 137L, 137L, 137L, 137L, 137L, 137L, 137L,
137L, 137L, 137L, 137L, 137L, 137L, 137L, 137L, 137L, 137L, 137L,
137L, 137L, 137L, 137L, 137L, 137L, 137L, 137L, 137L, 137L, 137L,
137L, 137L, 137L), action = c(0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L,
0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L,
0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 1L, 0L, 0L, 0L)), row.names = c(NA,
-37L), class = "data.frame")
agg
code item med q90 action
1: 137 11202 11 18.6 0
mydat[return != output]
item return code action output
1: 11202 19 137 0 11
2: 11202 20 137 0 11
3: 11202 19 137 0 11
4: 11202 21 137 0 11
5: 11202 25 137 0 11
6: 11202 21 137 0 11