Использование abind с массивами списка режимов

#r #arrays

#r #массивы

Вопрос:

У меня есть массив списка режимов, например, созданный из следующего кода tapply:

 my.data <- data.frame(expand.grid(species = c(1:3), year = c(1972:2000), VA = c(1:10), SA=c(1:3)))

test <- tapply(my.data$SA, list(my.data$species,my.data$year, my.data$VA), as.character)

mode(test)
#> [1] "list"

is.array(test)
#> [1] TRUE
  

Как мне использовать abind для добавления дополнительного измерения? Использование abind выдаст мне ошибку из-за режима «список»

 test2 <- abind(test, test[,,1])
#> Error in abind(test, test[, , 1]) : 
#>   can only supply one list-valued argument for ...
  

Заранее благодарю вас.

Ответ №1:

Вам нужно передать список в abind , поэтому просто поместите test и test[,,1] в список и передайте это:

 dim(test)
#> [1]  3 29 10

library(abind)
test2 <- abind(list(test, test[,,1]))

dim(test2)
#> [1]  3 29 11
  

Однако это может быть не тот результат, который вы ищете, поскольку в вашем исходном трехмерном массиве каждая «ячейка» фактически представляет собой список, содержащий вектор символов длиной 3. Возможно, нет никакого способа обойти это, если символьные векторы в ваших реальных данных имеют разную длину, но если все они имеют одинаковую длину, то лучше всего было бы построить 4-мерный массив, подобный этому:

 test <- array(unlist(test), dim = c(dim(test), length(test[[1]])))
dimnames(test) <- list(element = 1:3, year = 1972:2000, VA = 1:10, species = 1:3)

dim(test)
#> [1]  3 29 10  3
  

Теперь также будет намного проще отслеживать, с каким измерением вы работаете.

Например:

 test[,,VA = 3,]
#> , , species = 1
#> 
#>        year
#> element 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983
#>       1 "1"  "1"  "1"  "1"  "1"  "1"  "1"  "1"  "1"  "1"  "1"  "1" 
#>       2 "2"  "2"  "2"  "2"  "2"  "2"  "2"  "2"  "2"  "2"  "2"  "2" 
#>       3 "3"  "3"  "3"  "3"  "3"  "3"  "3"  "3"  "3"  "3"  "3"  "3" 
#>        year
#> element 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995
#>       1 "1"  "1"  "1"  "1"  "1"  "1"  "1"  "1"  "1"  "1"  "1"  "1" 
#>       2 "2"  "2"  "2"  "2"  "2"  "2"  "2"  "2"  "2"  "2"  "2"  "2" 
#>       3 "3"  "3"  "3"  "3"  "3"  "3"  "3"  "3"  "3"  "3"  "3"  "3" 
#>        year
#> element 1996 1997 1998 1999 2000
#>       1 "1"  "1"  "1"  "1"  "1" 
#>       2 "2"  "2"  "2"  "2"  "2" 
#>       3 "3"  "3"  "3"  "3"  "3" 
#> 
#> , , species = 2
#> 
#>        year
#> element 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983
#>       1 "1"  "1"  "1"  "1"  "1"  "1"  "1"  "1"  "1"  "1"  "1"  "1" 
#>       2 "2"  "2"  "2"  "2"  "2"  "2"  "2"  "2"  "2"  "2"  "2"  "2" 
#>       3 "3"  "3"  "3"  "3"  "3"  "3"  "3"  "3"  "3"  "3"  "3"  "3" 
#>        year
#> element 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995
#>       1 "1"  "1"  "1"  "1"  "1"  "1"  "1"  "1"  "1"  "1"  "1"  "1" 
#>       2 "2"  "2"  "2"  "2"  "2"  "2"  "2"  "2"  "2"  "2"  "2"  "2" 
#>       3 "3"  "3"  "3"  "3"  "3"  "3"  "3"  "3"  "3"  "3"  "3"  "3" 
#>        year
#> 
#> ...etc
  

Если вы хотите добавить дополнительный элемент в измерение «элемент», вы могли бы сделать

 test2 <- abind(list(test, test[1,,,]), along = 1)

test2
#> , , 1
#> 
#>   1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984
#> 1 "1"  "1"  "1"  "1"  "1"  "1"  "1"  "1"  "1"  "1"  "1"  "1"  "1" 
#> 2 "2"  "2"  "2"  "2"  "2"  "2"  "2"  "2"  "2"  "2"  "2"  "2"  "2" 
#> 3 "3"  "3"  "3"  "3"  "3"  "3"  "3"  "3"  "3"  "3"  "3"  "3"  "3" 
#>   "1"  "1"  "1"  "1"  "1"  "1"  "1"  "1"  "1"  "1"  "1"  "1"  "1" 
#>   1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997
#> 1 "1"  "1"  "1"  "1"  "1"  "1"  "1"  "1"  "1"  "1"  "1"  "1"  "1" 
#> 2 "2"  "2"  "2"  "2"  "2"  "2"  "2"  "2"  "2"  "2"  "2"  "2"  "2" 
#> 3 "3"  "3"  "3"  "3"  "3"  "3"  "3"  "3"  "3"  "3"  "3"  "3"  "3" 
#>   "1"  "1"  "1"  "1"  "1"  "1"  "1"  "1"  "1"  "1"  "1"  "1"  "1" 
#>   1998 1999 2000
#> 1 "1"  "1"  "1" 
#> 2 "2"  "2"  "2" 
#> 3 "3"  "3"  "3" 
#>   "1"  "1"  "1" 
#>
#> ... etc
  

Комментарии:

1. Спасибо, Аллан, в реальном наборе данных фактически каждая ячейка имеет разную длину символьного вектора, и дополнительное измерение, которое мне нужно добавить, — это слияние двух исходных измерений (например, каждая ячейка test[,,3] = c(test[,,1], test[,,2]). Так что я все еще не могу найти решение…

2. @Miguel если вы просто хотите объединить векторы в каждой ячейке test[,,1] и test[,,2] в срез test[,,3] , вы можете сделать test[,,3] <- mapply(c, test[,,1], test[,,2], SIMPLIFY = FALSE)