Подмножество массива, используя вектор индексов - PullRequest
0 голосов
/ 26 октября 2018

Как я могу создать подмножество массива, используя вектор индексов? Это может быть легче показать на примере.

# I have this array
bn <- structure(c(0.8, 0.09, 0.11, 0.09, 0.8, 0.11, 0.11, 0.11, 0.78, 
0.18, 0.13, 0.69, 0.88, 0.07, 0.05, 0.25, 0.49, 0.26, 0.43, 0.2, 
0.37, 0.34, 0.39, 0.27, 0.13, 0.44, 0.42), class = "table", .Dim = c(3L, 
3L, 3L), .Dimnames = structure(list(D = c("a", "b", "c"), A = c("a", 
"b", "c"), C = c("a", "b", "c")), .Names = c("D", "A", "C")))    

# and matrix of indices (correspond to dimensions of bn)
input <- structure(c("a", "b", NA), .Dim = c(1L, 3L), 
                   .Dimnames = list(NULL, c("A", "C", "D")))

Я могу задать подмножество bn, напрямую проиндексировав, чтобы получить результат

bn[, input[,"A"], input[,"C"]]
#    a    b    c 
# 0.18 0.13 0.69 

Как я могу сделать это, не разбирая его так (хотя я не буду знать заранее размер массива, это будет количество входов + 1). Основываясь на r-subset-array-using-vector (хотя этот вопрос относится к списку, а не к массиву), я попытался

bn[, input[,c("A","C")]]
bn[, input[,c("A","C"), drop=FALSE]]

, которые дают ошибку в [.default (bn, input [, c ("A", "C"), drop = FALSE],):
неверное количество измерений

Это работает, но на принуждение уходит слишком много времени и построение индексов.

library(R.utils)
x = array(bn, dim=dim(bn), dimnames=dimnames(bn))
extract(x, indices=list("2"=1, "3"=2))

Я мог бы также melt данные и затем вытащить соответствующие строки, и есть также этот вопрос подмножество-массив-для-пар-индексов-в-г ] но решение предполагает размеры массива.

Есть краткий способ сделать это путем подстановки array?


Еще один вариант:

library(gRbase)
inp = input[,c("A", "C"), drop=FALSE]
ar_slice(bn, split(inp, colnames(inp)))

Но было бы неплохо без работы split

или лидерство от r2evans

ar_slice(bn, setNames(as.list(inp), colnames(inp)))

1 Ответ

0 голосов
/ 26 октября 2018

Один метод, хотя на самом деле он выглядит не очень красиво.

do.call(`[`, c(list(bn), list(TRUE), as.list(input[,c("A","C")])))
#    a    b    c 
# 0.18 0.13 0.69 

Я прослежу, как я это придумал.

  1. Сначала мы хотим простоbn[,"a","b"].Поймите, что это идентично db[TRUE,"a","b"].
  2. . Переведите [ в функцию, ala `[<-`(bn, TRUE, "a", "b").
  3. Зная, что вы хотите динамически генерировать список аргументов,Я сразу думаю о do.call, поэтому нам нужно знать, как создать (bn, TRUE, "a", "b") программно.Последняя часть:

    as.list(input[,c("A","C")])
    # $A
    # [1] "a"
    # $C
    # [1] "b"
    

    , поэтому мы можем создать целый ряд аргументов, добавив list -ified bn и TRUE:

    str( c(list(bn), list(TRUE), as.list(input[,c("A","C")])) )
    # List of 4
    #  $  : 'table' num [1:3, 1:3, 1:3] 0.8 0.09 0.11 0.09 0.8 0.11 0.11 0.11 0.78 0.18 ...
    #   ..- attr(*, "dimnames")=List of 3
    #   .. ..$ D: chr [1:3] "a" "b" "c"
    #   .. ..$ A: chr [1:3] "a" "b" "c"
    #   .. ..$ C: chr [1:3] "a" "b" "c"
    #  $  : logi TRUE
    #  $ A: chr "a"
    #  $ C: chr "b"
    

Предполагается, что ваша первая ось всегда "заполнена" (TRUE).Если вам необходимо определить это динамически, просто знайте, что вторые и последующие элементы списка в do.call являются вашими осями, определяйте их по своему усмотрению.

...