我有一个包含周数和日期数的表格,我想将其分组以创建所有可能的组合并使用它们创建一个新表格。
我试过了:
w =(book2$week_no)
d = (book2$day_no)
b=expand.grid(w,d)
b=b[c(TRUE,FALSE),]
它给了我所有的排列。
Var1 Var2
1 week1 day1
3 week2 day1
5 week1 day2
7 week2 day2
9 week1 day1
11 week2 day1
13 week1 day2
15 week2 day2
但我不知道如何使用这些结果创建新表。如果这是一个愚蠢的问题,我很抱歉。
答案 0 :(得分:3)
我认为您没有完全清楚地描述您所需的输出。您说您希望“分组以创建所有可能的组合”,但分组通常意味着聚合到较小的表中。从屏幕截图中看,您似乎希望从输入表中复制行以生成更大的表。更具体地说,您希望在每个唯一week_no
值的行集之间采用笛卡尔积,并且您希望产品行对按顺序堆叠在输出表中的附加皱纹,而不是并排加入。这是一个很好的方法:
df <- data.frame(raw_id=1:4,week_no=c('week1','week1','week2','week2'),day_no=c('day1','day2','day1','day2'),val=c(234,123,235,111),stringsAsFactors=F);
df[t(do.call(expand.grid,split(seq_len(nrow(df)),df$week_no))),];
## raw_id week_no day_no val
## 1 1 week1 day1 234
## 3 3 week2 day1 235
## 2 2 week1 day2 123
## 3.1 3 week2 day1 235
## 1.1 1 week1 day1 234
## 4 4 week2 day2 111
## 2.1 2 week1 day2 123
## 4.1 4 week2 day2 111
让我们打破这一点:
seq_len(nrow(df));
## [1] 1 2 3 4
上面生成了输入表中存在的行索引向量。
split(seq_len(nrow(df)),df$week_no);
## $week1
## [1] 1 2
##
## $week2
## [1] 3 4
##
然后我们在df$week_no
值上拆分向量以生成一个命名列表,其中每个组件保存输入表中week_no
的唯一值的行索引,并捕获该值很好地作为组件名称(虽然我们不会在解决方案中使用该名称)。
do.call(expand.grid,split(seq_len(nrow(df)),df$week_no));
## week1 week2
## 1 1 3
## 2 2 3
## 3 1 4
## 4 2 4
拆分列表的格式非常适合直接作为do.call()
的arg列表传递,以便调用expand.grid()
。这就是我们如何在两个week_no
值之间得到行索引的笛卡尔积。
我们可以通过索引输入表中的上述行对来获得所需的输出,通过沿着行从左到右跟随索引表顺序堆叠它们,然后沿着列从上到下(通常只是调用“按行”)。但是有两个原因导致我们不能直接使用上面的对象作为行维度下标:(1)它是一个data.frame,我们需要一个简单的行索引向量,(2)即使我们可以传递它作为行下标的矩阵,矩阵数据自然地在内存中“按列”排列,这意味着索引将按照所需输出的错误顺序进行。
t(do.call(expand.grid,split(seq_len(nrow(df)),df$week_no)));
## [,1] [,2] [,3] [,4]
## week1 1 2 1 2
## week2 3 3 4 4
我们可以通过单次调用t()
来解决上述两个问题,它会自动将data.frame强制转换为矩阵并对其进行转置,因此自然的“by column”遍历将导致正确的索引顺序。
df[t(do.call(expand.grid,split(seq_len(nrow(df)),df$week_no))),];
## raw_id week_no day_no val
## 1 1 week1 day1 234
## 3 3 week2 day1 235
## 2 2 week1 day2 123
## 3.1 3 week2 day1 235
## 1.1 1 week1 day1 234
## 4 4 week2 day2 111
## 2.1 2 week1 day2 123
## 4.1 4 week2 day2 111
瞧。
啊,几乎忘记了所需输出中的group
列。由于输出表是以常规方式生成的,这意味着它是由输入行的笛卡尔积生成的,因此我们可以在事后推导出组值。假设您已将上述结果存储为res
:
res$group <- rep(seq_len(prod(table(df$week_no))),each=length(unique(df$week_no)));
res;
## raw_id week_no day_no val group
## 1 1 week1 day1 234 1
## 3 3 week2 day1 235 1
## 2 2 week1 day2 123 2
## 3.1 3 week2 day1 235 2
## 1.1 1 week1 day1 234 3
## 4 4 week2 day2 111 3
## 2.1 2 week1 day2 123 4
## 4.1 4 week2 day2 111 4
我刚才意识到,你的问题和我的答案都没有解决week_no
中三个或更多个唯一值的情况。我的解决方案恰好在所有week_no
行集之间采用可变笛卡尔积,但我意识到您可能更喜欢在所有week_no
行集之间仅使用二元笛卡尔积,这需要不同的解决方案。这是一个具有挑战性和有趣的问题,但我相信我明白了:
df <- data.frame(raw_id=1:6,week_no=c('week1','week1','week2','week2','week3','week3'),day_no=c('day1','day2','day1','day2','day3','day3'),val=c(234,123,235,111,300,400),stringsAsFactors=F);
df;
## raw_id week_no day_no val
## 1 1 week1 day1 234
## 2 2 week1 day2 123
## 3 3 week2 day1 235
## 4 4 week2 day2 111
## 5 5 week3 day3 300
## 6 6 week3 day3 400
res <- df[t(do.call(rbind,apply(combn(seq_along(unique(df$week_no)),2L),2L,function(is,rs) expand.grid(rs[[is[1L]]],rs[[is[2L]]]),split(seq_len(nrow(df)),df$week_no)))),];
res$group <- rep(seq_len(nrow(res)%/%2L),each=2L);
res;
## raw_id week_no day_no val group
## 1 1 week1 day1 234 1
## 3 3 week2 day1 235 1
## 2 2 week1 day2 123 2
## 3.1 3 week2 day1 235 2
## 1.1 1 week1 day1 234 3
## 4 4 week2 day2 111 3
## 2.1 2 week1 day2 123 4
## 4.1 4 week2 day2 111 4
## 1.2 1 week1 day1 234 5
## 5 5 week3 day3 300 5
## 2.2 2 week1 day2 123 6
## 5.1 5 week3 day3 300 6
## 1.3 1 week1 day1 234 7
## 6 6 week3 day3 400 7
## 2.3 2 week1 day2 123 8
## 6.1 6 week3 day3 400 8
## 3.2 3 week2 day1 235 9
## 5.2 5 week3 day3 300 9
## 4.2 4 week2 day2 111 10
## 5.3 5 week3 day3 300 10
## 3.3 3 week2 day1 235 11
## 6.2 6 week3 day3 400 11
## 4.3 4 week2 day2 111 12
## 6.3 6 week3 day3 400 12
我们可以将上述结果与我在第一个解决方案中得到的结果进行比较:
res <- df[t(do.call(expand.grid,split(seq_len(nrow(df)),df$week_no))),];
res$group <- rep(seq_len(prod(table(df$week_no))),each=length(unique(df$week_no)));
res;
## raw_id week_no day_no val group
## 1 1 week1 day1 234 1
## 3 3 week2 day1 235 1
## 5 5 week3 day3 300 1
## 2 2 week1 day2 123 2
## 3.1 3 week2 day1 235 2
## 5.1 5 week3 day3 300 2
## 1.1 1 week1 day1 234 3
## 4 4 week2 day2 111 3
## 5.2 5 week3 day3 300 3
## 2.1 2 week1 day2 123 4
## 4.1 4 week2 day2 111 4
## 5.3 5 week3 day3 300 4
## 1.2 1 week1 day1 234 5
## 3.2 3 week2 day1 235 5
## 6 6 week3 day3 400 5
## 2.2 2 week1 day2 123 6
## 3.3 3 week2 day1 235 6
## 6.1 6 week3 day3 400 6
## 1.3 1 week1 day1 234 7
## 4.2 4 week2 day2 111 7
## 6.2 6 week3 day3 400 7
## 2.3 2 week1 day2 123 8
## 4.3 4 week2 day2 111 8
## 6.3 6 week3 day3 400 8
答案 1 :(得分:1)
仔细观察,重复排列(前四行与最后四行相同)
expand.grid
将为您提供两个向量的所有组合,而无需“分组”。
您的代码的更正版本将是:
b<-rbind(expand.grid(week = unique(w),day = unique(d)),expand.grid(day = d,week = w))
b$group<-rep(1:4,each = 2)
w<-sapply(1:nrow(b),FUN = function(z){
which(book2$week_no==b$week[z] & book2$day_no==b$day[z])
}
)
b$pre_raw_id<-w
b$val<-book2$val[w]