R 中的多维数组是否有 inner_join 等价物?

Is there an inner_join equivalent for multidimensional arrays in R?

对于 3d 数组是否有某种 inner_join 等价物,可以将 2d 结构连接到 3d 结构吗?

让我们看看这是否有意义:

我有一个 3d 整数数组(微生物组计数数据)。

我有 2d table 元数据。

二维元数据table(样本名称)中有一列与数组中第二维的标签相匹配。

我能否以某种方式加入这两者,以便保留数组结构并为每个样本添加元数据?

我是否必须将数组 melt/stack 变成一个超长的 2d table?

感谢您的帮助!

-编辑

假设我使用以下代码生成数组 a 和 "a" table "b":

a <- array(1:10,c(2,4,3))
b <- data.frame("thing" = c("stuff", "foo", "dodad"), "data" = c(10,20,30), "match" = c("first","second","third"))
dimnames(a) <- list(c("A", "B"), c("one", "two", "three", "four"), c("first", "second", "third"))

如您所见,我在 table "b" 中有一列 "match",我想 join/match 将其添加到维度名称 a[[3] ].

所以如果我们查看 "a" 和 "b"

> a
, , first

  one two three four
A   1   3     5    7
B   2   4     6    8

, , second

  one two three four
A   9   1     3    5
B  10   2     4    6

, , third

  one two three four
A   7   9     1    3
B   8  10     2    4

> b
  thing data  match
1 stuff   10  first
2   foo   20 second
3 dodad   30  third

我想要,例如,数组

, , third

      one two three four
    A   7   9     1    3
    B   8  10     2    4

将元素 "dodad" 和“30”与标签 "thing" 和 "data" 相关联。

对于真实的数据集,我想要 "patient name" 而不是 "thing" 和 "dilution" 而不是 "data" 并使用这些元素作为一种手段从数组中提取切片以进行 运行 统计分析。

你没有显示你想要的输出,所以我猜。

如果您从 a(dims AxBxC)和 b(dims DxE)开始,那么您应该得到一个包含 dims AxBxD 的数组。

a[,,b[,"match"]]
# , , first
#   one two three four
# A   1   3     5    7
# B   2   4     6    8
# , , second
#   one two three four
# A   9   1     3    5
# B  10   2     4    6
# , , third
#   one two three four
# A   7   9     1    3
# B   8  10     2    4

就组合输出而言,使用您提供的数据不可能发生:矩阵 a 具有所有数据必须相同 class 的约束,但您的 b 是具有不同 classes 的框架。因此,如果您需要在 a 中保留数字,在 b 中保留字符串或因子,那么您不能只将一个与另一个合并。

您有一些选择:

  1. 如果你的第二帧真的可以是矩阵,那我们就可以这样

    ### a naive conversion, your case may vary with real data
    bnum <- sapply(b, as.integer)
    dim(bnum) <- c(dim(bnum), 1)
    dimnames(bnum) <- list(rownames(b), colnames(b), NULL)
    bnum
    # , , 1
    #   thing data match
    # 1     3   10     1
    # 2     2   20     2
    # 3     1   30     3
    
    ### the solution
    abind::abind(
      apply(bnum[,-3,1], 2:1, rep, times = dim(a)[1]),
      a[,,bnum[,"match",1]],
      along = 2
    )
    # , , first
    #   thing data one two three four
    # A     3   10   1   3     5    7
    # B     3   10   2   4     6    8
    # , , second
    #   thing data one two three four
    # A     2   20   9   1     3    5
    # B     2   20  10   2     4    6
    # , , third
    #   thing data one two three four
    # A     1   30   7   9     1    3
    # B     1   30   8  10     2    4
    
  2. 如果您需要保持 b 原样,那么您无法制作 3 维数组。一个选项是以列表列的方式嵌套 a 的每一层。

    out <- within(b, { mtx = lapply(match, function(m) a[,,m]) })
    out
    #   thing data  match                     mtx
    # 1 stuff   10  first  1, 2, 3, 4, 5, 6, 7, 8
    # 2   foo   20 second 9, 10, 1, 2, 3, 4, 5, 6
    # 3 dodad   30  third 7, 8, 9, 10, 1, 2, 3, 4
    

    虽然看起来它丢失了 a 的 z 层布局,但这在控制台上的表现很差。还是不错的:

    out$mtx[[1]]
    #   one two three four
    # A   1   3     5    7
    # B   2   4     6    8
    

    如果您有兴趣,也可以使用 dplyrdata.table 来完成。

    library(dplyr)
    out <- b %>%
      mutate(mtx = lapply(match, function(m) a[,,m]))
    # option to use purrr::map instead of lapply
    
    library(data.table)
    out <- as.data.table(b)[, mtx := lapply(match, function(m) a[,,m]) ]