【问题标题】:Efficient way of combining subsetting and combn结合子集和组合的有效方法
【发布时间】:2017-02-17 11:25:25
【问题描述】:

我的问题是关于构建“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,其中包含ID 的列和values 的相应列表。

我尝试在第一部分基于expand.gridcombn 编写自己的函数,然后将melt 矩阵M 转换为长格式,并基于Classification 变量编写merge .这需要很多subsetmerge,然后又是rbind,所以花了太长时间。我尝试使用lapply,我似乎无法做到这一点。我的感觉是data.table 可能有一个聪明的方法,但我也无法做到这一点。

非常感谢任何帮助。

尼尔斯

【问题讨论】:

    标签: r


    【解决方案1】:

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

    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
    

    然后你可能想mergekDF 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
    

    【讨论】:

    • 感谢您的回答。但是,我想在合并之前限制组合,以便不会创建所有可能的匹配项,就像在您的示例中一样。由于 ID = 2 的行只有一个分类,我希望程序在这里给我 NA,因为没有一个分类的二进制扩展。另外,正如@thelatemail 的回答所指出的那样,我想合并成对的分类(所以 A-B 与 A-B),而不是单个分类(将 A 与 B 合并)。
    【解决方案2】:

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

    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
    

    【讨论】:

    • 感谢您的回答。这似乎几乎可以满足我的要求。有没有办法(a)当分类中只有一个值时(如 ID = 2)使值成为 NA,更重要的是,告诉 R 分类的顺序无关紧要,所以分类with A-B 与 B-A 相同,所以在合并操作期间我只能得到 6 个 ID = 1 的匹配项?矩阵M 是对称的,所以无论如何它都会给出相同的数值,但我想避免重复计算。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-01-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-10
    • 2018-03-19
    • 2021-02-20
    相关资源
    最近更新 更多