这里的数据
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), .Label = "52382МСК", class = "factor"),
item = c(11709L, 11709L, 11709L, 11709L, 11708L, 11708L,
11708L, 11710L, 11710L, 11710L, 11710L, 11710L, 11710L, 11710L,
11710L, 11710L, 11710L, 11710L, 11710L, 11710L, 11710L, 11710L,
11710L, 11710L, 11710L, 11710L, 11710L, 11710L), sales = c(30L,
10L, 20L, 15L, 2L, 10L, 3L, 30L, 10L, 20L, 15L, 2L, 10L,
3L, 30L, 10L, 20L, 15L, 2L, 10L, 3L, 30L, 10L, 20L, 15L,
2L, 10L, 3L), action = c(0L, 1L, 0L, 0L, 0L, 1L, 0L, 0L,
0L, 0L, 1L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 0L, 0L, 0L, 0L, 0L,
0L, 1L, 0L, 0L, 0L)), .Names = c("code", "item", "sales",
"action"), class = "data.frame", row.names = c(NA, -28L))
我有3组vars代码和项目。这里有3组:
code item
52382МСК 11709
52382МСК 11708
52382МСК 11710
我也有行动专栏。它只能有两个值零(0)或一(1)。
每个小组代表3个场景
52382МСК 11709
这是当我们有1个零类别的动作col时的情况。在动作col的第一类别之前,以及在动作col的第一类别之后的两个零。 注意:当我们有2个零类别的动作col时,可能是这种情况。在动作col的第一类别之前,并且在动作col的第一类别之后为1。
52382МСК 11708
这是当我们有1个零类别的动作col时的情况。在第一类动作列之后添加1个零。
52382МСК 11710
这是当我们有3个(或更多)零类别的动作col时的场景。并且在第一类动作列之后添加3(或更多)个零。
如何选择具有每种情况的组?
即Mydat1
是具有第一种情况的组,
Mydat2
是具有第二种情况的小组,
Mydat3
是具有第三种情况的小组
输出很简单
mydat1
code item sales action
52382МСК 11709 30 0
52382МСК 11709 10 1
52382МСК 11709 20 0
52382МСК 11709 15 0
mydat2
code item sales action
52382МСК 11708 2 0
52382МСК 11708 10 1
52382МСК 11708 3 0
mydat3
code item sales action
52382МСК 11710 30 0
52382МСК 11710 10 0
52382МСК 11710 20 0
52382МСК 11710 15 1
52382МСК 11710 2 0
52382МСК 11710 10 0
52382МСК 11710 3 0
52382МСК 11710 30 0
52382МСК 11710 10 0
52382МСК 11710 20 0
52382МСК 11710 15 1
52382МСК 11710 2 0
52382МСК 11710 10 0
52382МСК 11710 3 0
52382МСК 11710 30 0
52382МСК 11710 10 0
52382МСК 11710 20 0
52382МСК 11710 15 1
52382МСК 11710 2 0
52382МСК 11710 10 0
52382МСК 11710 3 0
我忘了,当我们有1个零类别的动作col时,可能是场景。在动作col的第一类别之前,以及在动作col的第一类别之后的三个零。 或当我们有3个零类别的动作栏时的场景。在动作col的第一类别之前,并且在动作col的第一类别之后为1。
(mydat4)
也可以 我们有2个零类别的动作col的场景。在动作col的第一类别之前,以及在动作col的第一类别之后的三个零。 或当我们有3个零类别的动作栏时的场景。在动作col的第一类之前,并且在动作col的第一类之后为2。
(mydat5)
I.E。它只能在这些情况下工作。
我找到了下一组,它只有一行
code item sales action
52499МСК 11202 2 0
如果数据只有一行,那将是6种情况怎么办?
也可以这样
code item sales action
52499МСК 11202 2 0
52499МСК 11202 2 1
或
code item sales action
52499МСК 11202 2 0
52499МСК 11202 2 0
或
code item sales action
52499МСК 11202 2 1
52499МСК 11202 2 1
如果组中只有两行,则有7种情况
答案 0 :(得分:1)
如果我对您的理解正确,那么情况如下:
s1:0100
s2:010
s3:000 ... 1000 ...
s4:01000或00010
s5:001000或000100
s6:0或1
s7:01或00或10或11
如果是这样,那么方便地,这些方案中的每一个都有唯一的行数。 s1是4行,s2是3,s3是7 +,s4是5,s5是6,s6是1,s7是2。
利用这个事实,我们可以执行以下操作:
这将添加一个“方案”列,以指示是方案1、2、3、4还是5。我强烈建议您不要将数据帧分解为多个数据帧。我愿意猜测dplyr的library(dplyr)
mydat = structure(list(code = c("52382MCK", "52382MCK", "52382MCK", "52382MCK",
"52382MCK", "52382MCK", "52382MCK", "52382MCK", "52382MCK", "52382MCK",
"52382MCK", "52382MCK", "52382MCK", "52382MCK", "52382MCK", "52382MCK",
"52382MCK", "52382MCK", "52382MCK", "52382MCK", "52382MCK", "52382MCK",
"52382MCK", "52382MCK", "52382MCK", "52382MCK", "52382MCK", "52382MCK"
), item = c(11709L, 11709L, 11709L, 11709L, 11708L, 11708L, 11708L,
11710L, 11710L, 11710L, 11710L, 11710L, 11710L, 11710L, 11710L,
11710L, 11710L, 11710L, 11710L, 11710L, 11710L, 11710L, 11710L,
11710L, 11710L, 11710L, 11710L, 11710L), sales = c(30L, 10L,
20L, 15L, 2L, 10L, 3L, 30L, 10L, 20L, 15L, 2L, 10L, 3L, 30L,
10L, 20L, 15L, 2L, 10L, 3L, 30L, 10L, 20L, 15L, 2L, 10L, 3L),
action = c(0L, 1L, 0L, 0L, 0L, 1L, 0L, 0L, 0L, 0L, 1L, 0L,
0L, 0L, 0L, 0L, 0L, 1L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 0L, 0L,
0L)), class = "data.frame", row.names = c(NA, -28L), .Names = c("code",
"item", "sales", "action"))
mydat = mydat %>%
group_by(code, item) %>%
mutate(groups_item_count = n(),
scenario = case_when(groups_item_count == 4 ~ 1,
groups_item_count == 3 ~ 2,
groups_item_count >= 7 ~ 3,
groups_item_count == 5 ~ 4,
groups_item_count == 6 ~ 5,
groups_item_count == 1 ~ 6,
groups_item_count == 2 ~ 7))
和filter()
函数对于完成接下来要完成的任务会更有效。但是,如果您坚持要针对每种情况将其分解为单独的数据帧,则可以执行以下操作:
group_by()
答案 1 :(得分:1)
如果我理解正确,OP将按action
列中的零和一的模式对数据集中的不同组进行分类。在这个问题中,他描述了他希望在数据中找到的几种模式(称为“方案”)。
到目前为止,该问题已被编辑两次以添加更多方案。这表明OP的方案列表可能不完整。因此,我建议采用另一种方法来定义一组完整的方案(或0
和1
的模式),然后尝试在数据集中找到这些模式。
IIUC,不同的场景取决于0
的每个序列或条纹之前和之后连续1
的数量。 (此问题中的样本数据集只有一个1
,但是OP发布了相关问题,其中数据包含最多三个1
的条纹。)
根据OP的描述,在0
连胜之前或之后,可能没有0
或最多三个连续1
的序列。另外,一个组只能包含0
个。
以此,可以创建所有可能的模式/场景的表:
library(data.table)
library(magrittr)
max_zeros <- 3
zeros <- sapply(0:max_zeros, stringr::str_dup, string = "0")
names(zeros) <- as.character(nchar(zeros))
sc <- CJ(zeros.before = zeros, zeros.after = zeros)[
, scenario.name := paste(nchar(zeros.before), nchar(zeros.after), sep = "-")][
, action.pattern := sprintf("%s1+(?=%s)", zeros.before, zeros.after)][]
# special case: all zero
sc0 <- data.table(
zeros.before = NA,
zeros.after = NA,
scenario.name = "no1",
action.pattern = "^0+$")
sc <- rbind(sc0, sc)
sc
zeros.before zeros.after scenario.name action.pattern 1: <NA> <NA> no1 ^0+$ 2: 0-0 1+(?=) 3: 0 0-1 1+(?=0) 4: 00 0-2 1+(?=00) 5: 000 0-3 1+(?=000) 6: 0 1-0 01+(?=) 7: 0 0 1-1 01+(?=0) 8: 0 00 1-2 01+(?=00) 9: 0 000 1-3 01+(?=000) 10: 00 2-0 001+(?=) 11: 00 0 2-1 001+(?=0) 12: 00 00 2-2 001+(?=00) 13: 00 000 2-3 001+(?=000) 14: 000 3-0 0001+(?=) 15: 000 0 3-1 0001+(?=0) 16: 000 00 3-2 0001+(?=00) 17: 000 000 3-3 0001+(?=000)
action.pattern
是正则表达式,用于查找通过折叠每个组的action
列而创建的字符串中的模式。它使用lookahead
查找重叠的图案。
scenario.name
是模式的简短描述。例如,第17行中的场景名称3-3
表示一种模式,该模式由三个0
,一个或多个1
的条纹,后跟三个0
组成,例如,0001000
或00011000
或00011111000
。第2行中的方案名称0-0
表示另一个特殊情况,其中模式仅由1
个组成。
现在,我们可以尝试在给定数据中查找模式。要搜索不同的模式,我们
action
列折叠为一个字符串,分别针对每个code
,item
组,action.pattern
的出现次数,并且请注意,mydat
已被修改为包括OP修改中的其他用例(请参见下面的数据部分)。
mydat[, paste(action, collapse = "") %>%
stringr::str_count(sc$action.pattern) %>%
t() %>%
as.data.table() %>%
setnames(sc$scenario.name),
by = .(code, item)]
code item no1 0-0 0-1 0-2 0-3 1-0 1-1 1-2 1-3 2-0 2-1 2-2 2-3 3-0 3-1 3-2 3-3
1: 52382MCK 11709 0 1 1 1 0 1 1 1 0 0 0 0 0 0 0 0 0
2: 52382MCK 11708 0 1 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0
3: 52382MCK 11710 0 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
4: 52499MCK 11202 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
5: 52499MCK 11203 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0
6: 52499MCK 11204 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
7: 52499MCK 11205 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
此表显示了每个组中“隐藏”了哪些可能的模式/场景以及发现了多少次事件/场景。
例如,第2行显示相应组中的模式0-0
("1"
),0-1
("10"
),1-0
({{ 1}})和"01"
(1-1
)已被发现一次。在所有找到的模式中,"010
(1-1
)最长,因此我们将其作为该组的分类。
第3行显示在相应的组中几乎所有模式都被发现了3次。但是,模式"010
(3-3
)最长,将被用作该组的分类。
我们可以自动选择最右边的模式作为组的分类:
"0001000"
class <- mydat[, .(scenario.name = sc$scenario.name[ paste(action, collapse = "") %>% stringr::str_count(sc$action.pattern) %>% is_greater_than(0) %>% which() %>% max() ]), by = .(code, item)][] class
也可以将分类加入 code item scenario.name
1: 52382MCK 11709 1-2
2: 52382MCK 11708 1-1
3: 52382MCK 11710 3-3
4: 52499MCK 11202 no1
5: 52499MCK 11203 1-0
6: 52499MCK 11204 no1
7: 52499MCK 11205 0-0
的每一行:
mydat
mydat[class, on = .(code, item)]
答案是基于我对OP的要求的理解,包括对OP生产数据集的大量推测和隐含假设。
code item sales action scenario.name
1: 52382MCK 11709 30 0 1-2
2: 52382MCK 11709 10 1 1-2
3: 52382MCK 11709 20 0 1-2
4: 52382MCK 11709 15 0 1-2
5: 52382MCK 11708 2 0 1-1
6: 52382MCK 11708 10 1 1-1
7: 52382MCK 11708 3 0 1-1
8: 52382MCK 11710 30 0 3-3
9: 52382MCK 11710 10 0 3-3
10: 52382MCK 11710 20 0 3-3
11: 52382MCK 11710 15 1 3-3
12: 52382MCK 11710 2 0 3-3
13: 52382MCK 11710 10 0 3-3
14: 52382MCK 11710 3 0 3-3
15: 52382MCK 11710 30 0 3-3
16: 52382MCK 11710 10 0 3-3
17: 52382MCK 11710 20 0 3-3
18: 52382MCK 11710 15 1 3-3
19: 52382MCK 11710 2 0 3-3
20: 52382MCK 11710 10 0 3-3
21: 52382MCK 11710 3 0 3-3
22: 52382MCK 11710 30 0 3-3
23: 52382MCK 11710 10 0 3-3
24: 52382MCK 11710 20 0 3-3
25: 52382MCK 11710 15 1 3-3
26: 52382MCK 11710 2 0 3-3
27: 52382MCK 11710 10 0 3-3
28: 52382MCK 11710 3 0 3-3
29: 52499MCK 11202 2 0 no1
30: 52499MCK 11203 2 0 1-0
31: 52499MCK 11203 2 1 1-0
32: 52499MCK 11204 2 0 no1
33: 52499MCK 11204 2 0 no1
34: 52499MCK 11205 2 1 0-0
35: 52499MCK 11205 2 1 0-0
code item sales action scenario.name
的增强版
mydat
OP有requested可以为17个场景中的每个场景创建一个单独的数据集。
通常,除非有充分的理由,附加要求或外部约束,否则我不建议您采用这种方法。想象一下,您是数据库管理员。您是否要在数据库中创建17个结构相同的独立表,而不是通过选择子集来控制处理的一个表?
但是,可以按场景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, 2L, 2L, 2L, 2L, 2L, 2L, 2L), .Label = c("52382MCK",
"52499MCK"), class = "factor"), item = c(11709L, 11709L, 11709L,
11709L, 11708L, 11708L, 11708L, 11710L, 11710L, 11710L, 11710L,
11710L, 11710L, 11710L, 11710L, 11710L, 11710L, 11710L, 11710L,
11710L, 11710L, 11710L, 11710L, 11710L, 11710L, 11710L, 11710L,
11710L, 11202L, 11203L, 11203L, 11204L, 11204L, 11205L, 11205L
), sales = c(30L, 10L, 20L, 15L, 2L, 10L, 3L, 30L, 10L, 20L,
15L, 2L, 10L, 3L, 30L, 10L, 20L, 15L, 2L, 10L, 3L, 30L, 10L,
20L, 15L, 2L, 10L, 3L, 2L, 2L, 2L, 2L, 2L, 2L, 2L), action = c(0L,
1L, 0L, 0L, 0L, 1L, 0L, 0L, 0L, 0L, 1L, 0L, 0L, 0L, 0L, 0L, 0L,
1L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 0L, 0L, 0L, 0L, 0L, 1L, 0L, 0L,
1L, 1L)), row.names = c(NA, -35L), class = "data.frame")
# coerce to data.table
setDT(mydat)
进行数据集
split()
split(mydat[class, on = .(code, item)], by = "scenario.name")
结果是一个列表data.tables。
可以从列表中选择单个元素,
$`1-2`
code item sales action scenario.name
1: 52382MCK 11709 30 0 1-2
2: 52382MCK 11709 10 1 1-2
3: 52382MCK 11709 20 0 1-2
4: 52382MCK 11709 15 0 1-2
$`1-1`
code item sales action scenario.name
1: 52382MCK 11708 2 0 1-1
2: 52382MCK 11708 10 1 1-1
3: 52382MCK 11708 3 0 1-1
$`3-3`
code item sales action scenario.name
1: 52382MCK 11710 30 0 3-3
2: 52382MCK 11710 10 0 3-3
3: 52382MCK 11710 20 0 3-3
4: 52382MCK 11710 15 1 3-3
5: 52382MCK 11710 2 0 3-3
6: 52382MCK 11710 10 0 3-3
7: 52382MCK 11710 3 0 3-3
8: 52382MCK 11710 30 0 3-3
9: 52382MCK 11710 10 0 3-3
10: 52382MCK 11710 20 0 3-3
11: 52382MCK 11710 15 1 3-3
12: 52382MCK 11710 2 0 3-3
13: 52382MCK 11710 10 0 3-3
14: 52382MCK 11710 3 0 3-3
15: 52382MCK 11710 30 0 3-3
16: 52382MCK 11710 10 0 3-3
17: 52382MCK 11710 20 0 3-3
18: 52382MCK 11710 15 1 3-3
19: 52382MCK 11710 2 0 3-3
20: 52382MCK 11710 10 0 3-3
21: 52382MCK 11710 3 0 3-3
code item sales action scenario.name
$no1
code item sales action scenario.name
1: 52499MCK 11202 2 0 no1
2: 52499MCK 11204 2 0 no1
3: 52499MCK 11204 2 0 no1
$`1-0`
code item sales action scenario.name
1: 52499MCK 11203 2 0 1-0
2: 52499MCK 11203 2 1 1-0
$`0-0`
code item sales action scenario.name
1: 52499MCK 11205 2 1 0-0
2: 52499MCK 11205 2 1 0-0
split(mydat[class, on = .(code, item)], by = "scenario.name")[["1-2"]]
如果出于某些原因仍需要使用许多单个数据对象来使工作区变得混乱,可以按以下步骤进行操作(不推荐)
code item sales action scenario.name
1: 52382MCK 11709 30 0 1-2
2: 52382MCK 11709 10 1 1-2
3: 52382MCK 11709 20 0 1-2
4: 52382MCK 11709 15 0 1-2
# workspace before ls()
[1] "class" "max_zeros" "mydat" "sc" "sc0" "zeros"
# create separate datasets mydat[class, on = .(code, item)] %>% split(by = "scenario.name") %>% set_names(names(.) %>% make.names()) %>% # make syntactically valid names list2env(.GlobalEnv)
<environment: R_GlobalEnv>
#workspace after ls()