Чтобы ответить на этот вопрос, мы должны посмотреть, как индексирование многомерного массива работает в Numpy. Давайте сначала скажем, что у вас есть массив x
из вашего вопроса. Буфер, назначенный x
, будет содержать 16 восходящих целых чисел от 0 до 15. Если вы обращаетесь к одному элементу, скажем x[i,j]
, NumPy должен определить расположение памяти этого элемента относительно начала буфера. Это делается путем вычисления фактического значения i*x.shape[1]+j
(и умножения на размер int для получения фактического смещения памяти).
Если вы извлекаете подмассив с помощью базовой нарезки, такой как y = x[0:2,0:2]
, результирующий объект будет совместно использовать базовый буфер с помощью x
. Но что произойдет, если вы получите y[i,j]
? NumPy не может использовать i*y.shape[1]+j
для вычисления смещения в массиве, поскольку данные, принадлежащие y
, не являются последовательными в памяти.
NumPy решает эту проблему, введя шаги . При вычислении смещения памяти для доступа к x[i,j]
то, что на самом деле вычисляется, является i*x.strides[0]+j*x.strides[1]
(и это уже включает в себя коэффициент для размера int):
x.strides
(16, 4)
Когда извлечено y
как и выше, NumPy не создает новый буфер, но делает создание нового объекта массива, ссылающегося на тот же буфер (иначе y
будет просто равен x
.) Новый объект массива будет имеют другую форму, тогда x
и, возможно, другое начальное смещение в буфере, но будут делиться шагами с x
(в этом случае, по крайней мере):
y.shape
(2,2)
y.strides
(16, 4)
Таким образом, вычисляя смещение памяти для y[i,j]
даст правильный результат.
Но что делать NumPy для чего-то вроде z=x[[1,3]]
? Механизм шагов не позволит правильно проиндексировать, если исходный буфер используется для z
. NumPy теоретически мог бы добавить еще более сложный механизм, чем шаги, но это сделало бы доступ к элементу относительно дорогостоящим, как-то игнорируя всю идею массива. Кроме того, представление больше не будет действительно легким объектом.
Это подробно описано в документации NumPy по индексированию .
О, и почти забыл о вашем фактическом вопросе: вот как сделать индексацию с несколькими списками работать как ожидалось:
x[[[1],[3]],[1,3]]
Это связано с тем, что массивы индексов транслируются на общий форма. Конечно, в этом конкретном примере вы также можете заниматься базовым нарезкой:
x[1::2, 1::2]
transposedAsdf = as.list(as.data.frame(t(as.data.frame(asdf))))
transposedAsdf
$V1
[1] 1 10
$V2
[1] 2 20
$V3
[1] 3 30
$V4
[1] 4 40
$V5
[1] 5 50
Вот один из способов:
split(do.call(cbind, asdf), 1:length(asdf[[1]]))
# Вот один из способов:
1`
# [1] 1 10
#
# Вот один из способов:
2`
# [1] 2 20
#
# Вот один из способов:
3`
# [1] 3 30
#
# Вот один из способов:
4`
# [1] 4 40
#
# Вот один из способов:
5`
# [1] 5 50
Опция с использованием data.table
data.table::transpose(asdf)
#[[1]]
#[1] 1 10
#[[2]]
#[1] 2 20
#[[3]]
#[1] 3 30
#[[4]]
#[1] 4 40
#[[5]]
#[1] 5 50
Решение с использованием пакета purrr
.
library(purrr)
asdf2 <- transpose(asdf) %>% map(unlist)
asdf2
# [[1]]
# [1] 1 10
#
# [[2]]
# [1] 2 20
#
# [[3]]
# [1] 3 30
#
# [[4]]
# [1] 4 40
#
# [[5]]
# [1] 5 50
Один вариант с Map
из base R
do.call(Map, c(f = c, asdf))