将每个观察值乘以另一个数据帧中的每个其他观察值

时间:2017-08-22 13:48:51

标签: r

我有三组数据。对于列中的每个观察,我想将其乘以其他数据集中相应列中的每个观察值。下面的例子有望解释;实际数据大约有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        ...        ...

3 个答案:

答案 0 :(得分:2)

以下是否符合您的要求?

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.frames提供两个mapply,它将应用您提供给第一列的任何函数,然后应用第二列,然后第三......在data.frames中。我们可以使用它来获取列式kronecker产品。

答案 1 :(得分: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

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

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和矩阵行索引,这使得很容易看到发生了什么。

答案 2 :(得分:1)

AWS SDK version is 3.33

给出

# 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" 中的paste替换为sapply

"*"

编辑:# not reproducible sapply(1:3, function(k){outer(outer(num_mat3[,k], num_mat2[,k], FUN = "*"), num_mat1[,k], FUN = "*")}) 包中还有一个函数返回列式Kronecker(Khatri-Rao)产品:

Matrix