组合子集和组合的有效方法

时间:2017-02-17 02:38:07

标签: r

我的问题是关于构建类似“combn by”函数的快速有效的方法,以及合并两个数据集的问题。我的数据大致如下:

DF <- data.frame(c(1, 1, 1, 2), c("A", "B", "C", "A"))
colnames(DF) <- c("ID", "Classification")
DF
  ID Classification
1  1              A
2  1              B
3  1              C
4  2              A
M <- matrix(data=c(1, 2, 3, 2, 4, 5, 3, 5, 6), nrow=3, ncol=3)
colnames(M) <- c("A", "B", "C")
rownames(M) <- c("A", "B", "C")
M
  A B C
A 1 4 7
B 2 5 8
C 3 6 9

我最终想要的结果就是这个(包括或不包括Classification1Classification2变量,我不在乎):

RESULT <- data.frame(c(1, 1, 1, 1, 1, 1, 2), c("A", "A", "A", "B", "B", "C", "A"), 
                     c("A", "B", "C", "B", "C", "C", NA), c(1, 2, 3, 4, 5, 6, NA))
colnames(RESULT) <- c("ID", "Classification1", "Classification2", "Value")
RESULT
  ID Classification1 Classification2 Value
1  1               A               A     1
2  1               A               B     2
3  1               A               C     3
4  1               B               B     4
5  1               B               C     5
6  1               C               C     6
7  2               A            <NA>    NA

所以本质上我想告诉R类似于:对于ID的每个唯一值,在Classification中创建因子的所有可能二元组合,为这些可能的组合中的每一个查找相应的矩阵M中的值,返回包含data.frame列的IDvalues的相应列表。

我已尝试根据expand.gridcombn为第一部分编写自己的函数,然后melt将矩阵M编成长格式,并{{1} 1}}基于merge变量。这需要很多Classificationsubset,然后又需要merge,所以花了太长时间。我尝试使用rbind,我似乎无法做到这一点。我的感觉是,lapply可能有一种聪明的方法,但我无法做到这一点。

非常感谢任何帮助。

尼尔斯

2 个答案:

答案 0 :(得分:0)

您可以先生成一个对矩阵进行操作的函数:

matrix.gather <- reshape2:::melt.matrix
matrix.gather(M)->k

这将为您提供矩阵行和列的组合。

> k
  Var1 Var2 value
1    A    A     1
2    B    A     2
3    C    A     3
4    A    B     2
5    B    B     4
6    C    B     5
7    A    C     3
8    B    C     5
9    C    C     6

您可能希望与merge k DF一样by Classification,如下所示:

merge(k,DF,by="Classification")

   Classification Var2 value ID
1               A    A     1  1
2               A    A     1  2
3               A    C     3  1
4               A    C     3  2
5               A    B     2  1
6               A    B     2  2
7               B    A     2  1
8               B    B     4  1
9               B    C     5  1
10              C    B     5  1
11              C    A     3  1
12              C    C     6  1

答案 1 :(得分:0)

与其他答案大致相同的逻辑,但我认为这会更恰当地限制组内的组合:

merge(
  merge(DF, DF, by="ID"),
  as.data.frame(as.table(M), responseName="Value"),
  by.x=2:3, by.y=1:2
)

#   Classification.x Classification.y ID Value
#1                 A                A  1     1
#2                 A                A  2     1
#3                 A                B  1     2
#4                 A                C  1     3
#5                 B                A  1     2
#6                 B                B  1     4
#7                 B                C  1     5
#8                 C                A  1     3
#9                 C                B  1     5
#10                C                C  1     6