重构/重塑数据框(R)

3

我的数据集为在项目上工作的人重复观察记录。我需要一个数据框,其中包含每个人和时间点的项目“组合”的两列列表。让我举个例子:

这是我的数据:

ID    Week    Project    
01    1       101
01    1       102 
01    1       103
01    2       101
01    2       102
02    1       101
02    1       102
02    2       101

第一人员(ID = 1)在第一周参与了三个项目。这意味着在该周,此人有六种可能的项目组合(project_i & project_j)。

这就是我需要的内容。

ID   Week    Project_i  Project_j
01    1      101        101
01    1      101        102
01    1      101        103
01    1      102        101
01    1      102        102    
01    1      102        103
01    1      103        101
01    1      103        102
01    1      103        103
01    2      101        101
01    2      101        102
01    2      102        101
01    2      102        102
02    1      101        101
02    1      101        102
02    1      102        101
02    1      102        102
02    2      101        101

每周只有一个项目的失败案例不是问题。

我尝试了基本的R和reshape2,但我无法理解这个问题。


目前,我在同一行中没有包含相同的项目ID(即101 101)。 - HJ_r
3个回答

6

以下是使用 dplyrtidyr 的解决方案。关键步骤是将 tidyr::complete()dplyr::group_by() 结合使用。

library(dplyr)
library(tidyr)

d %>% 
  rename(Project_i = Project) %>%
  mutate(Project_j = Project_i) %>% 
  group_by(ID, Week) %>%
  complete(Project_i, Project_j) %>%
  filter(Project_i != Project_j)

6
这里有一种方法:
library(data.table)
setDT(DT)

DT[, CJ(P1 = Project, P2 = Project)[P1 != P2], by=.(ID, Week)]

    ID Week  P1  P2
 1:  1    1 101 102
 2:  1    1 101 103
 3:  1    1 102 101
 4:  1    1 102 103
 5:  1    1 103 101
 6:  1    1 103 102
 7:  1    2 101 102
 8:  1    2 102 101
 9:  2    1 101 102
10:  2    1 102 101

CJ 是两个向量的笛卡尔积,取所有组合。

如果你不想要 (101,102) 和 (102,101) 两种情况,可以使用 P1 > P2 替代 P1 != P2。哦,原问题已经改变了...所以现在使用 P1 <= P2


这似乎可以工作,但r仍在运行。你认为对于200万个观测值,这会花费很长时间(或者根本不可行)吗? - HJ_r
1
@HJ_r 可能不行。你需要考虑你要解决的组合问题。你可以输入 combos = DT[, .(n = .N*(.N-1L)), by = .(ID, Week)] 查看问题规模。combos[, sum(n)] 将显示结果中的总行数,你还可以查看 combos[, summary(n)]combos[, hist(n)] 等内容。 - Frank

5
这是使用expand.grid的基本选项:
do.call(rbind, lapply(split(df, paste(df$ID, df$Week)), function(x){
    x2 <- expand.grid(ID = unique(x$ID), 
                      Week = unique(x$Week), 
                      Project_i = unique(x$Project), 
                      Project_j = unique(x$Project))
    # omit if 101 102 is different from 102 101; make `<` if 101 101 not possible
    x2[x2$Project_i <= x2$Project_j,]
}))

#       ID Week Project_i Project_j
# 1 1.1  1    1       101       101
# 1 1.4  1    1       101       102
# 1 1.5  1    1       102       102
# 1 1.7  1    1       101       103
# 1 1.8  1    1       102       103
# 1 1.9  1    1       103       103
# 1 2.1  1    2       101       101
# 1 2.3  1    2       101       102
# 1 2.4  1    2       102       102
# 2 1.1  2    1       101       101
# 2 1.3  2    1       101       102
# 2 1.4  2    1       102       102
# 2 2    2    2       101       101

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接