【问题标题】:Multiply each observation by every other observation in another dataframe将每个观察值乘以另一个数据框中的每个其他观察值
【发布时间】:2017-08-22 23:16:01
【问题描述】:

我有三组数据。对于列中的每个观察值,我想将其乘以其他数据集中相应列中的每个观察值。下面的例子有望解释;实际数据大约有 200 行。这是可能吗?我需要使用循环吗?我想在某个时候扩展它以包含更多数据集。

    Data set 1
        [A] [B] [C] 
    [1]  A1  B1  C1
    [2]  A2  B2  C2
    [3]  A3  B3  C3

    Data set 2
        [L] [M] [N] 
    [1]  L1  M1  N1
    [2]  L2  M2  N2
    [3]  L3  M3  N3

    Data set 3
        [X] [Y] [Z] 
    [1]  X1  Y1  Z1
    [2]  X2  Y2  Z2
    [3]  X3  Y3  Z3

    Output
              [,1]       [,2]       [,3]
    [1,]  A1*L1*X1   B1*M1*Y1   C1*N1*Z1
    [2,]  A1*L1*X2        ...        ...
    [3,]  A1*L1*X3        ...        ...
    [4,]  A1*L2*X1        ...        ...
    [5,]  A1*L2*X2        ...        ...
    [6,]  A1*L2*X3        ...        ...
    [7,]  A1*L3*X1        ...        ...
    [8,]  A1*L3*X2        ...        ...
    [9,]  A1*L3*X3        ...        ...
    [...]
    [27,] A3*L3*X3        ...        ...

【问题讨论】:

  • ?kronecker
  • @zx8754 - 我也是这么想的。但所需的输出显示 27 行。
  • 我认为他想要 Kronecker 产品,其中每个元素与其他矩阵的每个元素相乘。这类似于kronecker(matA, kronecker(matB,matC))
  • @coffeinjunky 可能只是在使用reducekronecker 之类的Reduce(kronecker,list(a,b,c))
  • 请编辑您的问题并清楚说明您想要实现的目标

标签: r


【解决方案1】:

以下是否符合您的要求?

A <- data.frame(matrix(1:6, ncol = 2)
B <- matrix(1:6, ncol = 2)
C <- matrix(1:6, ncol = 2)

out <- data.frame(mapply(kronecker, A, B))
out2 <- mapply(kronecker, out, C)
out2
      X1  X2
 [1,]  1  64
 [2,]  2  80
 [3,]  3  96
 [4,]  2  80
 [5,]  4 100
 [6,]  6 120
 [7,]  3  96
 [8,]  6 120
 [9,]  9 144
[10,]  2  80
[11,]  4 100
[12,]  6 120
[13,]  4 100
[14,]  8 125
[15,] 12 150
[16,]  6 120
[17,] 12 150
[18,] 18 180
[19,]  3  96
[20,]  6 120
[21,]  9 144
[22,]  6 120
[23,] 12 150
[24,] 18 180
[25,]  9 144
[26,] 18 180
[27,] 27 216

为了概括它,您可以使用例如:

hlpfun <- function(one, two) {
  data.frame(mapply(kronecker, one, two))
}

Reduce(hlpfun,list(A,B,C))

(归功于@Wen 的评论)

这里是使用@Ape 矩阵的测试用例,我将他的矩阵转换为data.frames 并将FUN = paste 提供给kroneker(如果您想实际乘以数值,请不要这样做):

hlpfun <- function(one, two) {
  data.frame(mapply(kronecker, one, two, MoreArgs = list(FUN = paste)))
}
Reduce(hlpfun,list(data.frame(mat1),data.frame(mat2),data.frame(mat3)))
         X1       X2       X3
1  A1 L1 X1 B1 M1 Y1 C1 N1 Z1
2  A1 L1 X2 B1 M1 Y2 C1 N1 Z2
3  A1 L1 X3 B1 M1 Y3 C1 N1 Z3
4  A1 L2 X1 B1 M2 Y1 C1 N2 Z1
5  A1 L2 X2 B1 M2 Y2 C1 N2 Z2
6  A1 L2 X3 B1 M2 Y3 C1 N2 Z3
7  A1 L3 X1 B1 M3 Y1 C1 N3 Z1
8  A1 L3 X2 B1 M3 Y2 C1 N3 Z2
9  A1 L3 X3 B1 M3 Y3 C1 N3 Z3
10 A2 L1 X1 B2 M1 Y1 C2 N1 Z1
11 A2 L1 X2 B2 M1 Y2 C2 N1 Z2
12 A2 L1 X3 B2 M1 Y3 C2 N1 Z3
13 A2 L2 X1 B2 M2 Y1 C2 N2 Z1
14 A2 L2 X2 B2 M2 Y2 C2 N2 Z2
15 A2 L2 X3 B2 M2 Y3 C2 N2 Z3
16 A2 L3 X1 B2 M3 Y1 C2 N3 Z1
17 A2 L3 X2 B2 M3 Y2 C2 N3 Z2
18 A2 L3 X3 B2 M3 Y3 C2 N3 Z3
19 A3 L1 X1 B3 M1 Y1 C3 N1 Z1
20 A3 L1 X2 B3 M1 Y2 C3 N1 Z2
21 A3 L1 X3 B3 M1 Y3 C3 N1 Z3
22 A3 L2 X1 B3 M2 Y1 C3 N2 Z1
23 A3 L2 X2 B3 M2 Y2 C3 N2 Z2
24 A3 L2 X3 B3 M2 Y3 C3 N2 Z3
25 A3 L3 X1 B3 M3 Y1 C3 N3 Z1
26 A3 L3 X2 B3 M3 Y2 C3 N3 Z2
27 A3 L3 X3 B3 M3 Y3 C3 N3 Z3

添加一个小解释,mapply 同时通过两个参数并对其应用一个函数。 data.frames 是列表,其中每一列都是列表中的一个元素,因此通过提供两个 data.framesmapply,它会将您提供的任何功能应用于第一列,然后是第二列,然后是第三列...... data.frames。我们可以使用它来获得列式kronecker 产品。

【讨论】:

    【解决方案2】:

    一种选择是简单地以适当的模式复制每个数据帧的行,然后将它们相乘。

    数据:

    (A <- matrix(1:6, 3))
    #      [,1] [,2]
    # [1,]    1    4
    # [2,]    2    5
    # [3,]    3    6
    (B <- matrix(2:5, 2))
    #      [,1] [,2]
    # [1,]    2    4
    # [2,]    3    5
    (C <- matrix(3:8, 3))
    #      [,1] [,2]
    # [1,]    3    6
    # [2,]    4    7
    # [3,]    5    8
    

    A 的每一行都应该被复制足够的次数,以使 B 的每一行与 C 的每一行配对:

    A[rep(seq_len(nrow(A)), each=nrow(B)*nrow(C)),]
    #       [,1] [,2]
    #  [1,]    1    4
    #  [2,]    1    4
    #  [3,]    1    4
    #  [4,]    1    4
    #  [5,]    1    4
    #  [6,]    1    4
    #  [7,]    2    5
    #  [8,]    2    5
    #  [9,]    2    5
    # [10,]    2    5
    # [11,]    2    5
    # [12,]    2    5
    # [13,]    3    6
    # [14,]    3    6
    # [15,]    3    6
    # [16,]    3    6
    # [17,]    3    6
    # [18,]    3    6
    

    C 的每一行都需要复制 B 的行,A 的每一行都需要再次复制这种模式:

    B[rep(rep(seq_len(nrow(B)), each=nrow(C)), nrow(A)),]
    #       [,1] [,2]
    #  [1,]    2    4
    #  [2,]    2    4
    #  [3,]    2    4
    #  [4,]    3    5
    #  [5,]    3    5
    #  [6,]    3    5
    #  [7,]    2    4
    #  [8,]    2    4
    #  [9,]    2    4
    # [10,]    3    5
    # [11,]    3    5
    # [12,]    3    5
    # [13,]    2    4
    # [14,]    2    4
    # [15,]    2    4
    # [16,]    3    5
    # [17,]    3    5
    # [18,]    3    5
    

    C的行需要对A的每一行和B的每一行重复一次:

    C[rep(seq_len(nrow(C)), nrow(A)*nrow(B)),]
    #       [,1] [,2]
    #  [1,]    3    6
    #  [2,]    4    7
    #  [3,]    5    8
    #  [4,]    3    6
    #  [5,]    4    7
    #  [6,]    5    8
    #  [7,]    3    6
    #  [8,]    4    7
    #  [9,]    5    8
    # [10,]    3    6
    # [11,]    4    7
    # [12,]    5    8
    # [13,]    3    6
    # [14,]    4    7
    # [15,]    5    8
    # [16,]    3    6
    # [17,]    4    7
    # [18,]    5    8
    

    将这三个相乘得到结果:

    A[rep(seq_len(nrow(A)), each=nrow(B)*nrow(C)),] *
      B[rep(rep(seq_len(nrow(B)), each=nrow(C)), nrow(A)),] *
      C[rep(seq_len(nrow(C)), nrow(A)*nrow(B)),]
    #       [,1] [,2]
    #  [1,]    6   96
    #  [2,]    8  112
    #  [3,]   10  128
    #  [4,]    9  120
    #  [5,]   12  140
    #  [6,]   15  160
    #  [7,]   12  120
    #  [8,]   16  140
    #  [9,]   20  160
    # [10,]   18  150
    # [11,]   24  175
    # [12,]   30  200
    # [13,]   18  144
    # [14,]   24  168
    # [15,]   30  192
    # [16,]   27  180
    # [17,]   36  210
    # [18,]   45  240
    

    这比kronecker 之类的类型要多得多,也更难扩展到更多的矩阵,但我想将它作为一个选项发布,因为它只使用rep 和矩阵行索引,这使得很容易看到发生了什么。

    【讨论】:

      【解决方案3】:
      # data
      mat1 <- matrix(paste0(rep(c("A","B","C"), each = 3), rep(1:3, times = 3)), ncol = 3)
      mat2 <- matrix(paste0(rep(c("L","M","N"), each = 3), rep(1:3, times = 3)), ncol = 3)
      mat3 <- matrix(paste0(rep(c("X","Y","Z"), each = 3), rep(1:3, times = 3)), ncol = 3)
      
      sapply(1:3, function(k){outer(outer(mat3[,k], mat2[,k], FUN = "paste"), 
          mat1[,k], FUN = "paste")})
      

      给予

            [,1]       [,2]       [,3]      
       [1,] "X1 L1 A1" "Y1 M1 B1" "Z1 N1 C1"
       [2,] "X2 L1 A1" "Y2 M1 B1" "Z2 N1 C1"
       [3,] "X3 L1 A1" "Y3 M1 B1" "Z3 N1 C1"
       [4,] "X1 L2 A1" "Y1 M2 B1" "Z1 N2 C1"
       ....
       [27,] "X3 L3 A3" "Y3 M3 B3" "Z3 N3 C3"
      

      要“相乘”数字矩阵,请将sapply 中的paste 替换为"*"

      # not reproducible
      sapply(1:3, function(k){outer(outer(num_mat3[,k], num_mat2[,k], FUN = "*"), 
          num_mat1[,k], FUN = "*")})
      

      编辑:Matrix 包中还有一个函数,它返回按列排列的 Kronecker (Khatri-Rao) 乘积:

      library(Matrix)
      KhatriRao(KhatriRao(num_mat1, num_mat2), num_mat3)
      

      【讨论】:

        猜你喜欢
        • 2017-10-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-08-18
        相关资源
        最近更新 更多