Существует ли эквивалентная переменная inner_join для многомерных массивов в R? - PullRequest
0 голосов
/ 01 апреля 2020

Существует ли какой-то эквивалент inner_join для трехмерных массивов, и можно ли это сделать, соединяя 2d структуру с 3d структурой?

Давайте посмотрим, имеет ли это смысл:

У меня есть трехмерный массив целых чисел (данные подсчета микробиомов).

  • Размер 1: копия 1: 100
  • Размер 2: Образцы
  • Размер 3: Таксоны

У меня есть 2d таблица метаданных.

  • Размер 1: образцы
  • Размер 2: тип метаданных (разведение, дата выборки и т. д. c)

Существует один столбец в 2-й таблице метаданных (имена образцов), который соответствует меткам второго измерения в массиве.

Могу ли я как-то объединить эти два, чтобы я сохранил структуру массива и добавил метаданные для каждого образца?

Нужно ли просто расплавить / сложить массив в супердлинную 2d таблицу ?

Спасибо за любую помощь!

-edit

Допустим, я сгенерировал массив a и "a" таблицу "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"))

Как видите, у меня есть столбец "match" в таблице "b", к которому я хотел бы присоединиться / сопоставить имена измерений 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» были связаны с это с метками «вещь» и «данные».

Для реального набора данных я хочу иметь «имя пациента» вместо «вещь» и «разбавление» вместо «данные» и использовать эти элементы как средство для извлечения срезов из массива проводить статистический анализ.

1 Ответ

0 голосов
/ 01 апреля 2020

Вы не показываете, какой выход вы намереваетесь, поэтому я угадаю.

Если вы начнете с a (с dims AxBx C) и 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 имеет ограничение на то, что все данные должны быть тот же класс, но ваш b - это фрейм с разными классами. Поэтому, если вам нужно хранить числа в 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
    

    Хотя похоже, что он потерял макет z-слоя a, это всего лишь плохое представление на консоли. Это все еще хорошо:

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

    Это также можно сделать с dplyr и data.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]) ]
    
...